diff options
Diffstat (limited to 'arch/um')
49 files changed, 619 insertions, 455 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 7218c754505..e82764f75e7 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -544,7 +544,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device, | |||
544 | 544 | ||
545 | ops = NULL; | 545 | ops = NULL; |
546 | data = NULL; | 546 | data = NULL; |
547 | for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ | 547 | for(i = 0; i < ARRAY_SIZE(chan_table); i++){ |
548 | entry = &chan_table[i]; | 548 | entry = &chan_table[i]; |
549 | if(!strncmp(str, entry->key, strlen(entry->key))){ | 549 | if(!strncmp(str, entry->key, strlen(entry->key))){ |
550 | ops = entry->ops; | 550 | ops = entry->ops; |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index b414522f768..79610b5ce67 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -497,7 +497,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, | |||
497 | } | 497 | } |
498 | 498 | ||
499 | error = NULL; | 499 | error = NULL; |
500 | size = sizeof(default_buf)/sizeof(default_buf[0]); | 500 | size = ARRAY_SIZE(default_buf); |
501 | buf = default_buf; | 501 | buf = default_buf; |
502 | 502 | ||
503 | while(1){ | 503 | while(1){ |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 9bfd405c3bd..5b2f5fe9e42 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "user.h" | 16 | #include "user.h" |
17 | #include "mconsole.h" | 17 | #include "mconsole.h" |
18 | #include "umid.h" | 18 | #include "umid.h" |
19 | #include "user_util.h" | ||
19 | 20 | ||
20 | static struct mconsole_command commands[] = { | 21 | static struct mconsole_command commands[] = { |
21 | /* With uts namespaces, uts information becomes process-specific, so | 22 | /* With uts namespaces, uts information becomes process-specific, so |
@@ -65,14 +66,14 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req) | |||
65 | struct mconsole_command *cmd; | 66 | struct mconsole_command *cmd; |
66 | int i; | 67 | int i; |
67 | 68 | ||
68 | for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){ | 69 | for(i = 0; i < ARRAY_SIZE(commands); i++){ |
69 | cmd = &commands[i]; | 70 | cmd = &commands[i]; |
70 | if(!strncmp(req->request.data, cmd->command, | 71 | if(!strncmp(req->request.data, cmd->command, |
71 | strlen(cmd->command))){ | 72 | strlen(cmd->command))){ |
72 | return(cmd); | 73 | return cmd; |
73 | } | 74 | } |
74 | } | 75 | } |
75 | return(NULL); | 76 | return NULL; |
76 | } | 77 | } |
77 | 78 | ||
78 | #define MIN(a,b) ((a)<(b) ? (a):(b)) | 79 | #define MIN(a,b) ((a)<(b) ? (a):(b)) |
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 501f95675d8..4a7966b2193 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -31,6 +31,11 @@ | |||
31 | #include "irq_user.h" | 31 | #include "irq_user.h" |
32 | #include "irq_kern.h" | 32 | #include "irq_kern.h" |
33 | 33 | ||
34 | static inline void set_ether_mac(struct net_device *dev, unsigned char *addr) | ||
35 | { | ||
36 | memcpy(dev->dev_addr, addr, ETH_ALEN); | ||
37 | } | ||
38 | |||
34 | #define DRIVER_NAME "uml-netdev" | 39 | #define DRIVER_NAME "uml-netdev" |
35 | 40 | ||
36 | static DEFINE_SPINLOCK(opened_lock); | 41 | static DEFINE_SPINLOCK(opened_lock); |
@@ -242,7 +247,7 @@ static int uml_net_set_mac(struct net_device *dev, void *addr) | |||
242 | struct sockaddr *hwaddr = addr; | 247 | struct sockaddr *hwaddr = addr; |
243 | 248 | ||
244 | spin_lock(&lp->lock); | 249 | spin_lock(&lp->lock); |
245 | memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); | 250 | set_ether_mac(dev, hwaddr->sa_data); |
246 | spin_unlock(&lp->lock); | 251 | spin_unlock(&lp->lock); |
247 | 252 | ||
248 | return(0); | 253 | return(0); |
@@ -790,13 +795,6 @@ void dev_ip_addr(void *d, unsigned char *bin_buf) | |||
790 | memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address)); | 795 | memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address)); |
791 | } | 796 | } |
792 | 797 | ||
793 | void set_ether_mac(void *d, unsigned char *addr) | ||
794 | { | ||
795 | struct net_device *dev = d; | ||
796 | |||
797 | memcpy(dev->dev_addr, addr, ETH_ALEN); | ||
798 | } | ||
799 | |||
800 | struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) | 798 | struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) |
801 | { | 799 | { |
802 | if((skb != NULL) && (skb_tailroom(skb) < extra)){ | 800 | if((skb != NULL) && (skb_tailroom(skb) < extra)){ |
diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index 466ff2c2f91..4c767c7adb9 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c | |||
@@ -76,7 +76,7 @@ int pcap_setup(char *str, char **mac_out, void *data) | |||
76 | if(host_if != NULL) | 76 | if(host_if != NULL) |
77 | init->host_if = host_if; | 77 | init->host_if = host_if; |
78 | 78 | ||
79 | for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){ | 79 | for(i = 0; i < ARRAY_SIZE(options); i++){ |
80 | if(options[i] == NULL) | 80 | if(options[i] == NULL) |
81 | continue; | 81 | continue; |
82 | if(!strcmp(options[i], "promisc")) | 82 | if(!strcmp(options[i], "promisc")) |
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index b98bdd8e052..89e1dc835a5 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h | |||
@@ -27,7 +27,6 @@ extern int ncpus; | |||
27 | extern char *linux_prog; | 27 | extern char *linux_prog; |
28 | extern char *gdb_init; | 28 | extern char *gdb_init; |
29 | extern int kmalloc_ok; | 29 | extern int kmalloc_ok; |
30 | extern int timer_irq_inited; | ||
31 | extern int jail; | 30 | extern int jail; |
32 | extern int nsyscalls; | 31 | extern int nsyscalls; |
33 | 32 | ||
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h index 1b5c0131a12..e93c6d3e893 100644 --- a/arch/um/include/longjmp.h +++ b/arch/um/include/longjmp.h | |||
@@ -1,9 +1,12 @@ | |||
1 | #ifndef __UML_LONGJMP_H | 1 | #ifndef __UML_LONGJMP_H |
2 | #define __UML_LONGJMP_H | 2 | #define __UML_LONGJMP_H |
3 | 3 | ||
4 | #include <setjmp.h> | 4 | #include "sysdep/archsetjmp.h" |
5 | #include "os.h" | 5 | #include "os.h" |
6 | 6 | ||
7 | extern int setjmp(jmp_buf); | ||
8 | extern void longjmp(jmp_buf, int); | ||
9 | |||
7 | #define UML_LONGJMP(buf, val) do { \ | 10 | #define UML_LONGJMP(buf, val) do { \ |
8 | longjmp(*buf, val); \ | 11 | longjmp(*buf, val); \ |
9 | } while(0) | 12 | } while(0) |
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h index 800c403920b..47ef7cb49a8 100644 --- a/arch/um/include/net_user.h +++ b/arch/um/include/net_user.h | |||
@@ -26,7 +26,6 @@ struct net_user_info { | |||
26 | 26 | ||
27 | extern void ether_user_init(void *data, void *dev); | 27 | extern void ether_user_init(void *data, void *dev); |
28 | extern void dev_ip_addr(void *d, unsigned char *bin_buf); | 28 | extern void dev_ip_addr(void *d, unsigned char *bin_buf); |
29 | extern void set_ether_mac(void *d, unsigned char *addr); | ||
30 | extern void iter_addresses(void *d, void (*cb)(unsigned char *, | 29 | extern void iter_addresses(void *d, void (*cb)(unsigned char *, |
31 | unsigned char *, void *), | 30 | unsigned char *, void *), |
32 | void *arg); | 31 | void *arg); |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 5316e8a4a4f..24fb6d8680e 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -276,9 +276,11 @@ extern int setjmp_wrapper(void (*proc)(void *, void *), ...); | |||
276 | 276 | ||
277 | extern void switch_timers(int to_real); | 277 | extern void switch_timers(int to_real); |
278 | extern void idle_sleep(int secs); | 278 | extern void idle_sleep(int secs); |
279 | extern int set_interval(int is_virtual); | ||
280 | #ifdef CONFIG_MODE_TT | ||
279 | extern void enable_timer(void); | 281 | extern void enable_timer(void); |
282 | #endif | ||
280 | extern void disable_timer(void); | 283 | extern void disable_timer(void); |
281 | extern void user_time_init(void); | ||
282 | extern void uml_idle_timer(void); | 284 | extern void uml_idle_timer(void); |
283 | extern unsigned long long os_nsecs(void); | 285 | extern unsigned long long os_nsecs(void); |
284 | 286 | ||
@@ -329,6 +331,7 @@ extern void os_set_ioignore(void); | |||
329 | extern void init_irq_signals(int on_sigstack); | 331 | extern void init_irq_signals(int on_sigstack); |
330 | 332 | ||
331 | /* sigio.c */ | 333 | /* sigio.c */ |
334 | extern int add_sigio_fd(int fd); | ||
332 | extern int ignore_sigio_fd(int fd); | 335 | extern int ignore_sigio_fd(int fd); |
333 | extern void maybe_sigio_broken(int fd, int read); | 336 | extern void maybe_sigio_broken(int fd, int read); |
334 | 337 | ||
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 83b688ca198..f845b3629a6 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #define __REGISTERS_H | 7 | #define __REGISTERS_H |
8 | 8 | ||
9 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
10 | #include "sysdep/archsetjmp.h" | ||
10 | 11 | ||
11 | extern void init_thread_registers(union uml_pt_regs *to); | 12 | extern void init_thread_registers(union uml_pt_regs *to); |
12 | extern int save_fp_registers(int pid, unsigned long *fp_regs); | 13 | extern int save_fp_registers(int pid, unsigned long *fp_regs); |
@@ -15,6 +16,6 @@ extern void save_registers(int pid, union uml_pt_regs *regs); | |||
15 | extern void restore_registers(int pid, union uml_pt_regs *regs); | 16 | extern void restore_registers(int pid, union uml_pt_regs *regs); |
16 | extern void init_registers(int pid); | 17 | extern void init_registers(int pid); |
17 | extern void get_safe_registers(unsigned long * regs, unsigned long * fp_regs); | 18 | 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); | 19 | extern unsigned long get_thread_reg(int reg, jmp_buf *buf); |
19 | 20 | ||
20 | #endif | 21 | #endif |
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h new file mode 100644 index 00000000000..ea1ba3d42ae --- /dev/null +++ b/arch/um/include/sysdep-i386/archsetjmp.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * arch/i386/include/klibc/archsetjmp.h | ||
3 | */ | ||
4 | |||
5 | #ifndef _KLIBC_ARCHSETJMP_H | ||
6 | #define _KLIBC_ARCHSETJMP_H | ||
7 | |||
8 | struct __jmp_buf { | ||
9 | unsigned int __ebx; | ||
10 | unsigned int __esp; | ||
11 | unsigned int __ebp; | ||
12 | unsigned int __esi; | ||
13 | unsigned int __edi; | ||
14 | unsigned int __eip; | ||
15 | }; | ||
16 | |||
17 | typedef struct __jmp_buf jmp_buf[1]; | ||
18 | |||
19 | #endif /* _SETJMP_H */ | ||
diff --git a/arch/um/include/sysdep-i386/signal.h b/arch/um/include/sysdep-i386/signal.h deleted file mode 100644 index 07518b16213..00000000000 --- a/arch/um/include/sysdep-i386/signal.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __I386_SIGNAL_H_ | ||
7 | #define __I386_SIGNAL_H_ | ||
8 | |||
9 | #include <signal.h> | ||
10 | |||
11 | #define ARCH_SIGHDLR_PARAM int sig | ||
12 | |||
13 | #define ARCH_GET_SIGCONTEXT(sc, sig) \ | ||
14 | do sc = (struct sigcontext *) (&sig + 1); while(0) | ||
15 | |||
16 | #endif | ||
17 | |||
18 | /* | ||
19 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
20 | * Emacs will notice this stuff at the end of the file and automatically | ||
21 | * adjust the settings for this buffer only. This must remain at the end | ||
22 | * of the file. | ||
23 | * --------------------------------------------------------------------------- | ||
24 | * Local variables: | ||
25 | * c-file-style: "linux" | ||
26 | * End: | ||
27 | */ | ||
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h new file mode 100644 index 00000000000..454fc60aff6 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/archsetjmp.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * arch/x86_64/include/klibc/archsetjmp.h | ||
3 | */ | ||
4 | |||
5 | #ifndef _KLIBC_ARCHSETJMP_H | ||
6 | #define _KLIBC_ARCHSETJMP_H | ||
7 | |||
8 | struct __jmp_buf { | ||
9 | unsigned long __rbx; | ||
10 | unsigned long __rsp; | ||
11 | unsigned long __rbp; | ||
12 | unsigned long __r12; | ||
13 | unsigned long __r13; | ||
14 | unsigned long __r14; | ||
15 | unsigned long __r15; | ||
16 | unsigned long __rip; | ||
17 | }; | ||
18 | |||
19 | typedef struct __jmp_buf jmp_buf[1]; | ||
20 | |||
21 | #endif /* _SETJMP_H */ | ||
diff --git a/arch/um/include/sysdep-x86_64/signal.h b/arch/um/include/sysdep-x86_64/signal.h deleted file mode 100644 index 6142897af3d..00000000000 --- a/arch/um/include/sysdep-x86_64/signal.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 PathScale, Inc | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #ifndef __X86_64_SIGNAL_H_ | ||
7 | #define __X86_64_SIGNAL_H_ | ||
8 | |||
9 | #define ARCH_SIGHDLR_PARAM int sig | ||
10 | |||
11 | #define ARCH_GET_SIGCONTEXT(sc, sig_addr) \ | ||
12 | do { \ | ||
13 | struct ucontext *__uc; \ | ||
14 | asm("movq %%rdx, %0" : "=r" (__uc)); \ | ||
15 | sc = (struct sigcontext *) &__uc->uc_mcontext; \ | ||
16 | } while(0) | ||
17 | |||
18 | #endif | ||
19 | |||
20 | /* | ||
21 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
22 | * Emacs will notice this stuff at the end of the file and automatically | ||
23 | * adjust the settings for this buffer only. This must remain at the end | ||
24 | * of the file. | ||
25 | * --------------------------------------------------------------------------- | ||
26 | * Local variables: | ||
27 | * c-file-style: "linux" | ||
28 | * End: | ||
29 | */ | ||
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index fc38a6d5906..0561c43b468 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -41,9 +41,11 @@ static long execve1(char *file, char __user * __user *argv, | |||
41 | long error; | 41 | long error; |
42 | 42 | ||
43 | #ifdef CONFIG_TTY_LOG | 43 | #ifdef CONFIG_TTY_LOG |
44 | task_lock(current); | 44 | mutex_lock(&tty_mutex); |
45 | task_lock(current); /* FIXME: is this needed ? */ | ||
45 | log_exec(argv, current->signal->tty); | 46 | log_exec(argv, current->signal->tty); |
46 | task_unlock(current); | 47 | task_unlock(current); |
48 | mutex_unlock(&tty_mutex); | ||
47 | #endif | 49 | #endif |
48 | error = do_execve(file, argv, env, ¤t->thread.regs); | 50 | error = do_execve(file, argv, env, ¤t->thread.regs); |
49 | if (error == 0){ | 51 | if (error == 0){ |
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 589c69a7504..ce7f233fc49 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -142,19 +142,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
142 | .events = events, | 142 | .events = events, |
143 | .current_events = 0 } ); | 143 | .current_events = 0 } ); |
144 | 144 | ||
145 | /* Critical section - locked by a spinlock because this stuff can | ||
146 | * be changed from interrupt handlers. The stuff above is done | ||
147 | * outside the lock because it allocates memory. | ||
148 | */ | ||
149 | |||
150 | /* Actually, it only looks like it can be called from interrupt | ||
151 | * context. The culprit is reactivate_fd, which calls | ||
152 | * maybe_sigio_broken, which calls write_sigio_workaround, | ||
153 | * which calls activate_fd. However, write_sigio_workaround should | ||
154 | * only be called once, at boot time. That would make it clear that | ||
155 | * this is called only from process context, and can be locked with | ||
156 | * a semaphore. | ||
157 | */ | ||
158 | spin_lock_irqsave(&irq_lock, flags); | 145 | spin_lock_irqsave(&irq_lock, flags); |
159 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 146 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { |
160 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { | 147 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { |
@@ -165,7 +152,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
165 | } | 152 | } |
166 | } | 153 | } |
167 | 154 | ||
168 | /*-------------*/ | ||
169 | if (type == IRQ_WRITE) | 155 | if (type == IRQ_WRITE) |
170 | fd = -1; | 156 | fd = -1; |
171 | 157 | ||
@@ -198,7 +184,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
198 | 184 | ||
199 | spin_lock_irqsave(&irq_lock, flags); | 185 | spin_lock_irqsave(&irq_lock, flags); |
200 | } | 186 | } |
201 | /*-------------*/ | ||
202 | 187 | ||
203 | *last_irq_ptr = new_fd; | 188 | *last_irq_ptr = new_fd; |
204 | last_irq_ptr = &new_fd->next; | 189 | last_irq_ptr = &new_fd->next; |
@@ -210,14 +195,14 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
210 | */ | 195 | */ |
211 | maybe_sigio_broken(fd, (type == IRQ_READ)); | 196 | maybe_sigio_broken(fd, (type == IRQ_READ)); |
212 | 197 | ||
213 | return(0); | 198 | return 0; |
214 | 199 | ||
215 | out_unlock: | 200 | out_unlock: |
216 | spin_unlock_irqrestore(&irq_lock, flags); | 201 | spin_unlock_irqrestore(&irq_lock, flags); |
217 | out_kfree: | 202 | out_kfree: |
218 | kfree(new_fd); | 203 | kfree(new_fd); |
219 | out: | 204 | out: |
220 | return(err); | 205 | return err; |
221 | } | 206 | } |
222 | 207 | ||
223 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | 208 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) |
@@ -302,10 +287,7 @@ void reactivate_fd(int fd, int irqnum) | |||
302 | os_set_pollfd(i, irq->fd); | 287 | os_set_pollfd(i, irq->fd); |
303 | spin_unlock_irqrestore(&irq_lock, flags); | 288 | spin_unlock_irqrestore(&irq_lock, flags); |
304 | 289 | ||
305 | /* This calls activate_fd, so it has to be outside the critical | 290 | add_sigio_fd(fd); |
306 | * section. | ||
307 | */ | ||
308 | maybe_sigio_broken(fd, (irq->type == IRQ_READ)); | ||
309 | } | 291 | } |
310 | 292 | ||
311 | void deactivate_fd(int fd, int irqnum) | 293 | void deactivate_fd(int fd, int irqnum) |
@@ -316,11 +298,15 @@ void deactivate_fd(int fd, int irqnum) | |||
316 | 298 | ||
317 | spin_lock_irqsave(&irq_lock, flags); | 299 | spin_lock_irqsave(&irq_lock, flags); |
318 | irq = find_irq_by_fd(fd, irqnum, &i); | 300 | irq = find_irq_by_fd(fd, irqnum, &i); |
319 | if (irq == NULL) | 301 | if(irq == NULL){ |
320 | goto out; | 302 | spin_unlock_irqrestore(&irq_lock, flags); |
303 | return; | ||
304 | } | ||
305 | |||
321 | os_set_pollfd(i, -1); | 306 | os_set_pollfd(i, -1); |
322 | out: | ||
323 | spin_unlock_irqrestore(&irq_lock, flags); | 307 | spin_unlock_irqrestore(&irq_lock, flags); |
308 | |||
309 | ignore_sigio_fd(fd); | ||
324 | } | 310 | } |
325 | 311 | ||
326 | int deactivate_all_fds(void) | 312 | int deactivate_all_fds(void) |
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 61280167c56..93121c6d26e 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -79,8 +79,10 @@ void mem_init(void) | |||
79 | 79 | ||
80 | /* this will put all low memory onto the freelists */ | 80 | /* this will put all low memory onto the freelists */ |
81 | totalram_pages = free_all_bootmem(); | 81 | totalram_pages = free_all_bootmem(); |
82 | #ifdef CONFIG_HIGHMEM | ||
82 | totalhigh_pages = highmem >> PAGE_SHIFT; | 83 | totalhigh_pages = highmem >> PAGE_SHIFT; |
83 | totalram_pages += totalhigh_pages; | 84 | totalram_pages += totalhigh_pages; |
85 | #endif | ||
84 | num_physpages = totalram_pages; | 86 | num_physpages = totalram_pages; |
85 | max_pfn = totalram_pages; | 87 | max_pfn = totalram_pages; |
86 | printk(KERN_INFO "Memory: %luk available\n", | 88 | printk(KERN_INFO "Memory: %luk available\n", |
@@ -221,10 +223,13 @@ void paging_init(void) | |||
221 | 223 | ||
222 | empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); | 224 | empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); |
223 | empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); | 225 | empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); |
224 | for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) | 226 | for(i = 0; i < ARRAY_SIZE(zones_size); i++) |
225 | zones_size[i] = 0; | 227 | zones_size[i] = 0; |
228 | |||
226 | zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); | 229 | zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); |
230 | #ifdef CONFIG_HIGHMEM | ||
227 | zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; | 231 | zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; |
232 | #endif | ||
228 | free_area_init(zones_size); | 233 | free_area_init(zones_size); |
229 | 234 | ||
230 | /* | 235 | /* |
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index f6a5a502120..537895d68ad 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "linux/proc_fs.h" | 23 | #include "linux/proc_fs.h" |
24 | #include "linux/ptrace.h" | 24 | #include "linux/ptrace.h" |
25 | #include "linux/random.h" | 25 | #include "linux/random.h" |
26 | #include "linux/personality.h" | ||
26 | #include "asm/unistd.h" | 27 | #include "asm/unistd.h" |
27 | #include "asm/mman.h" | 28 | #include "asm/mman.h" |
28 | #include "asm/segment.h" | 29 | #include "asm/segment.h" |
@@ -476,7 +477,7 @@ int singlestepping(void * t) | |||
476 | #ifndef arch_align_stack | 477 | #ifndef arch_align_stack |
477 | unsigned long arch_align_stack(unsigned long sp) | 478 | unsigned long arch_align_stack(unsigned long sp) |
478 | { | 479 | { |
479 | if (randomize_va_space) | 480 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
480 | sp -= get_random_int() % 8192; | 481 | sp -= get_random_int() % 8192; |
481 | return sp & ~0xf; | 482 | return sp & ~0xf; |
482 | } | 483 | } |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 3ef73bf2e78..f602623644a 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -22,7 +22,7 @@ static void kill_idlers(int me) | |||
22 | struct task_struct *p; | 22 | struct task_struct *p; |
23 | int i; | 23 | int i; |
24 | 24 | ||
25 | for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){ | 25 | for(i = 0; i < ARRAY_SIZE(idle_threads); i++){ |
26 | p = idle_threads[i]; | 26 | p = idle_threads[i]; |
27 | if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) | 27 | if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) |
28 | os_kill_process(p->thread.mode.tt.extern_pid, 0); | 28 | os_kill_process(p->thread.mode.tt.extern_pid, 0); |
@@ -62,14 +62,3 @@ void machine_halt(void) | |||
62 | { | 62 | { |
63 | machine_power_off(); | 63 | machine_power_off(); |
64 | } | 64 | } |
65 | |||
66 | /* | ||
67 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
68 | * Emacs will notice this stuff at the end of the file and automatically | ||
69 | * adjust the settings for this buffer only. This must remain at the end | ||
70 | * of the file. | ||
71 | * --------------------------------------------------------------------------- | ||
72 | * Local variables: | ||
73 | * c-file-style: "linux" | ||
74 | * End: | ||
75 | */ | ||
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 624ca238d1f..79c22707a63 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
@@ -55,7 +55,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
55 | * destroy_context_skas. | 55 | * destroy_context_skas. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | mm->context.skas.last_page_table = pmd_page_kernel(*pmd); | 58 | mm->context.skas.last_page_table = pmd_page_vaddr(*pmd); |
59 | #ifdef CONFIG_3_LEVEL_PGTABLES | 59 | #ifdef CONFIG_3_LEVEL_PGTABLES |
60 | mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); | 60 | mm->context.skas.last_pmd = (unsigned long) __va(pud_val(*pud)); |
61 | #endif | 61 | #endif |
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 552ca1cb984..2454bbd9555 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c | |||
@@ -35,9 +35,6 @@ unsigned long long sched_clock(void) | |||
35 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); | 35 | return (unsigned long long)jiffies_64 * (1000000000 / HZ); |
36 | } | 36 | } |
37 | 37 | ||
38 | /* Changed at early boot */ | ||
39 | int timer_irq_inited = 0; | ||
40 | |||
41 | static unsigned long long prev_nsecs; | 38 | static unsigned long long prev_nsecs; |
42 | #ifdef CONFIG_UML_REAL_TIME_CLOCK | 39 | #ifdef CONFIG_UML_REAL_TIME_CLOCK |
43 | static long long delta; /* Deviation per interval */ | 40 | static long long delta; /* Deviation per interval */ |
@@ -113,12 +110,13 @@ static void register_timer(void) | |||
113 | 110 | ||
114 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); | 111 | err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); |
115 | if(err != 0) | 112 | if(err != 0) |
116 | printk(KERN_ERR "timer_init : request_irq failed - " | 113 | printk(KERN_ERR "register_timer : request_irq failed - " |
117 | "errno = %d\n", -err); | 114 | "errno = %d\n", -err); |
118 | 115 | ||
119 | timer_irq_inited = 1; | 116 | err = set_interval(1); |
120 | 117 | if(err != 0) | |
121 | user_time_init(); | 118 | printk(KERN_ERR "register_timer : set_interval failed - " |
119 | "errno = %d\n", -err); | ||
122 | } | 120 | } |
123 | 121 | ||
124 | extern void (*late_time_init)(void); | 122 | extern void (*late_time_init)(void); |
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index f5b0636f9ad..54a5ff25645 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -16,12 +16,12 @@ | |||
16 | #include "os.h" | 16 | #include "os.h" |
17 | 17 | ||
18 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, | 18 | static int add_mmap(unsigned long virt, unsigned long phys, unsigned long len, |
19 | int r, int w, int x, struct host_vm_op *ops, int *index, | 19 | int r, int w, int x, struct host_vm_op *ops, int *index, |
20 | int last_filled, union mm_context *mmu, void **flush, | 20 | int last_filled, union mm_context *mmu, void **flush, |
21 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 21 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
22 | int, int, void **)) | 22 | int, int, void **)) |
23 | { | 23 | { |
24 | __u64 offset; | 24 | __u64 offset; |
25 | struct host_vm_op *last; | 25 | struct host_vm_op *last; |
26 | int fd, ret = 0; | 26 | int fd, ret = 0; |
27 | 27 | ||
@@ -89,7 +89,7 @@ static int add_munmap(unsigned long addr, unsigned long len, | |||
89 | static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | 89 | static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, |
90 | int x, struct host_vm_op *ops, int *index, | 90 | int x, struct host_vm_op *ops, int *index, |
91 | int last_filled, union mm_context *mmu, void **flush, | 91 | int last_filled, union mm_context *mmu, void **flush, |
92 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 92 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
93 | int, int, void **)) | 93 | int, int, void **)) |
94 | { | 94 | { |
95 | struct host_vm_op *last; | 95 | struct host_vm_op *last; |
@@ -124,105 +124,105 @@ static int add_mprotect(unsigned long addr, unsigned long len, int r, int w, | |||
124 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) | 124 | #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1)) |
125 | 125 | ||
126 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | 126 | void fix_range_common(struct mm_struct *mm, unsigned long start_addr, |
127 | unsigned long end_addr, int force, | 127 | unsigned long end_addr, int force, |
128 | int (*do_ops)(union mm_context *, struct host_vm_op *, | 128 | int (*do_ops)(union mm_context *, struct host_vm_op *, |
129 | int, int, void **)) | 129 | int, int, void **)) |
130 | { | 130 | { |
131 | pgd_t *npgd; | 131 | pgd_t *npgd; |
132 | pud_t *npud; | 132 | pud_t *npud; |
133 | pmd_t *npmd; | 133 | pmd_t *npmd; |
134 | pte_t *npte; | 134 | pte_t *npte; |
135 | union mm_context *mmu = &mm->context; | 135 | union mm_context *mmu = &mm->context; |
136 | unsigned long addr, end; | 136 | unsigned long addr, end; |
137 | int r, w, x; | 137 | int r, w, x; |
138 | struct host_vm_op ops[1]; | 138 | struct host_vm_op ops[1]; |
139 | void *flush = NULL; | 139 | void *flush = NULL; |
140 | int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1; | 140 | int op_index = -1, last_op = ARRAY_SIZE(ops) - 1; |
141 | int ret = 0; | 141 | int ret = 0; |
142 | 142 | ||
143 | if(mm == NULL) return; | 143 | if(mm == NULL) |
144 | 144 | return; | |
145 | ops[0].type = NONE; | 145 | |
146 | for(addr = start_addr; addr < end_addr && !ret;){ | 146 | ops[0].type = NONE; |
147 | npgd = pgd_offset(mm, addr); | 147 | for(addr = start_addr; addr < end_addr && !ret;){ |
148 | if(!pgd_present(*npgd)){ | 148 | npgd = pgd_offset(mm, addr); |
149 | end = ADD_ROUND(addr, PGDIR_SIZE); | 149 | if(!pgd_present(*npgd)){ |
150 | if(end > end_addr) | 150 | end = ADD_ROUND(addr, PGDIR_SIZE); |
151 | end = end_addr; | 151 | if(end > end_addr) |
152 | if(force || pgd_newpage(*npgd)){ | 152 | end = end_addr; |
153 | ret = add_munmap(addr, end - addr, ops, | 153 | if(force || pgd_newpage(*npgd)){ |
154 | &op_index, last_op, mmu, | 154 | ret = add_munmap(addr, end - addr, ops, |
155 | &flush, do_ops); | 155 | &op_index, last_op, mmu, |
156 | pgd_mkuptodate(*npgd); | 156 | &flush, do_ops); |
157 | } | 157 | pgd_mkuptodate(*npgd); |
158 | addr = end; | 158 | } |
159 | continue; | 159 | addr = end; |
160 | } | 160 | continue; |
161 | 161 | } | |
162 | npud = pud_offset(npgd, addr); | 162 | |
163 | if(!pud_present(*npud)){ | 163 | npud = pud_offset(npgd, addr); |
164 | end = ADD_ROUND(addr, PUD_SIZE); | 164 | if(!pud_present(*npud)){ |
165 | if(end > end_addr) | 165 | end = ADD_ROUND(addr, PUD_SIZE); |
166 | end = end_addr; | 166 | if(end > end_addr) |
167 | if(force || pud_newpage(*npud)){ | 167 | end = end_addr; |
168 | ret = add_munmap(addr, end - addr, ops, | 168 | if(force || pud_newpage(*npud)){ |
169 | &op_index, last_op, mmu, | 169 | ret = add_munmap(addr, end - addr, ops, |
170 | &flush, do_ops); | 170 | &op_index, last_op, mmu, |
171 | pud_mkuptodate(*npud); | 171 | &flush, do_ops); |
172 | } | 172 | pud_mkuptodate(*npud); |
173 | addr = end; | 173 | } |
174 | continue; | 174 | addr = end; |
175 | } | 175 | continue; |
176 | 176 | } | |
177 | npmd = pmd_offset(npud, addr); | 177 | |
178 | if(!pmd_present(*npmd)){ | 178 | npmd = pmd_offset(npud, addr); |
179 | end = ADD_ROUND(addr, PMD_SIZE); | 179 | if(!pmd_present(*npmd)){ |
180 | if(end > end_addr) | 180 | end = ADD_ROUND(addr, PMD_SIZE); |
181 | end = end_addr; | 181 | if(end > end_addr) |
182 | if(force || pmd_newpage(*npmd)){ | 182 | end = end_addr; |
183 | ret = add_munmap(addr, end - addr, ops, | 183 | if(force || pmd_newpage(*npmd)){ |
184 | &op_index, last_op, mmu, | 184 | ret = add_munmap(addr, end - addr, ops, |
185 | &flush, do_ops); | 185 | &op_index, last_op, mmu, |
186 | pmd_mkuptodate(*npmd); | 186 | &flush, do_ops); |
187 | } | 187 | pmd_mkuptodate(*npmd); |
188 | addr = end; | 188 | } |
189 | continue; | 189 | addr = end; |
190 | } | 190 | continue; |
191 | 191 | } | |
192 | npte = pte_offset_kernel(npmd, addr); | 192 | |
193 | r = pte_read(*npte); | 193 | npte = pte_offset_kernel(npmd, addr); |
194 | w = pte_write(*npte); | 194 | r = pte_read(*npte); |
195 | x = pte_exec(*npte); | 195 | w = pte_write(*npte); |
196 | x = pte_exec(*npte); | ||
196 | if (!pte_young(*npte)) { | 197 | if (!pte_young(*npte)) { |
197 | r = 0; | 198 | r = 0; |
198 | w = 0; | 199 | w = 0; |
199 | } else if (!pte_dirty(*npte)) { | 200 | } else if (!pte_dirty(*npte)) { |
200 | w = 0; | 201 | w = 0; |
201 | } | 202 | } |
202 | if(force || pte_newpage(*npte)){ | 203 | if(force || pte_newpage(*npte)){ |
203 | if(pte_present(*npte)) | 204 | if(pte_present(*npte)) |
204 | ret = add_mmap(addr, | 205 | ret = add_mmap(addr, |
205 | pte_val(*npte) & PAGE_MASK, | 206 | pte_val(*npte) & PAGE_MASK, |
206 | PAGE_SIZE, r, w, x, ops, | 207 | PAGE_SIZE, r, w, x, ops, |
207 | &op_index, last_op, mmu, | 208 | &op_index, last_op, mmu, |
208 | &flush, do_ops); | 209 | &flush, do_ops); |
209 | else ret = add_munmap(addr, PAGE_SIZE, ops, | 210 | else ret = add_munmap(addr, PAGE_SIZE, ops, |
210 | &op_index, last_op, mmu, | 211 | &op_index, last_op, mmu, |
211 | &flush, do_ops); | 212 | &flush, do_ops); |
212 | } | 213 | } |
213 | else if(pte_newprot(*npte)) | 214 | else if(pte_newprot(*npte)) |
214 | ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, | 215 | ret = add_mprotect(addr, PAGE_SIZE, r, w, x, ops, |
215 | &op_index, last_op, mmu, | 216 | &op_index, last_op, mmu, |
216 | &flush, do_ops); | 217 | &flush, do_ops); |
217 | 218 | ||
218 | *npte = pte_mkuptodate(*npte); | 219 | *npte = pte_mkuptodate(*npte); |
219 | addr += PAGE_SIZE; | 220 | addr += PAGE_SIZE; |
220 | } | 221 | } |
221 | |||
222 | if(!ret) | 222 | if(!ret) |
223 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); | 223 | ret = (*do_ops)(mmu, ops, op_index, 1, &flush); |
224 | 224 | ||
225 | /* This is not an else because ret is modified above */ | 225 | /* This is not an else because ret is modified above */ |
226 | if(ret) { | 226 | if(ret) { |
227 | printk("fix_range_common: failed, killing current process\n"); | 227 | printk("fix_range_common: failed, killing current process\n"); |
228 | force_sig(SIGKILL, current); | 228 | force_sig(SIGKILL, current); |
@@ -231,160 +231,160 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, | |||
231 | 231 | ||
232 | int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | 232 | int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) |
233 | { | 233 | { |
234 | struct mm_struct *mm; | 234 | struct mm_struct *mm; |
235 | pgd_t *pgd; | 235 | pgd_t *pgd; |
236 | pud_t *pud; | 236 | pud_t *pud; |
237 | pmd_t *pmd; | 237 | pmd_t *pmd; |
238 | pte_t *pte; | 238 | pte_t *pte; |
239 | unsigned long addr, last; | 239 | unsigned long addr, last; |
240 | int updated = 0, err; | 240 | int updated = 0, err; |
241 | 241 | ||
242 | mm = &init_mm; | 242 | mm = &init_mm; |
243 | for(addr = start; addr < end;){ | 243 | for(addr = start; addr < end;){ |
244 | pgd = pgd_offset(mm, addr); | 244 | pgd = pgd_offset(mm, addr); |
245 | if(!pgd_present(*pgd)){ | 245 | if(!pgd_present(*pgd)){ |
246 | last = ADD_ROUND(addr, PGDIR_SIZE); | 246 | last = ADD_ROUND(addr, PGDIR_SIZE); |
247 | if(last > end) | 247 | if(last > end) |
248 | last = end; | 248 | last = end; |
249 | if(pgd_newpage(*pgd)){ | 249 | if(pgd_newpage(*pgd)){ |
250 | updated = 1; | 250 | updated = 1; |
251 | err = os_unmap_memory((void *) addr, | 251 | err = os_unmap_memory((void *) addr, |
252 | last - addr); | 252 | last - addr); |
253 | if(err < 0) | 253 | if(err < 0) |
254 | panic("munmap failed, errno = %d\n", | 254 | panic("munmap failed, errno = %d\n", |
255 | -err); | 255 | -err); |
256 | } | 256 | } |
257 | addr = last; | 257 | addr = last; |
258 | continue; | 258 | continue; |
259 | } | 259 | } |
260 | 260 | ||
261 | pud = pud_offset(pgd, addr); | 261 | pud = pud_offset(pgd, addr); |
262 | if(!pud_present(*pud)){ | 262 | if(!pud_present(*pud)){ |
263 | last = ADD_ROUND(addr, PUD_SIZE); | 263 | last = ADD_ROUND(addr, PUD_SIZE); |
264 | if(last > end) | 264 | if(last > end) |
265 | last = end; | 265 | last = end; |
266 | if(pud_newpage(*pud)){ | 266 | if(pud_newpage(*pud)){ |
267 | updated = 1; | 267 | updated = 1; |
268 | err = os_unmap_memory((void *) addr, | 268 | err = os_unmap_memory((void *) addr, |
269 | last - addr); | 269 | last - addr); |
270 | if(err < 0) | 270 | if(err < 0) |
271 | panic("munmap failed, errno = %d\n", | 271 | panic("munmap failed, errno = %d\n", |
272 | -err); | 272 | -err); |
273 | } | 273 | } |
274 | addr = last; | 274 | addr = last; |
275 | continue; | 275 | continue; |
276 | } | 276 | } |
277 | 277 | ||
278 | pmd = pmd_offset(pud, addr); | 278 | pmd = pmd_offset(pud, addr); |
279 | if(!pmd_present(*pmd)){ | 279 | if(!pmd_present(*pmd)){ |
280 | last = ADD_ROUND(addr, PMD_SIZE); | 280 | last = ADD_ROUND(addr, PMD_SIZE); |
281 | if(last > end) | 281 | if(last > end) |
282 | last = end; | 282 | last = end; |
283 | if(pmd_newpage(*pmd)){ | 283 | if(pmd_newpage(*pmd)){ |
284 | updated = 1; | 284 | updated = 1; |
285 | err = os_unmap_memory((void *) addr, | 285 | err = os_unmap_memory((void *) addr, |
286 | last - addr); | 286 | last - addr); |
287 | if(err < 0) | 287 | if(err < 0) |
288 | panic("munmap failed, errno = %d\n", | 288 | panic("munmap failed, errno = %d\n", |
289 | -err); | 289 | -err); |
290 | } | 290 | } |
291 | addr = last; | 291 | addr = last; |
292 | continue; | 292 | continue; |
293 | } | 293 | } |
294 | 294 | ||
295 | pte = pte_offset_kernel(pmd, addr); | 295 | pte = pte_offset_kernel(pmd, addr); |
296 | if(!pte_present(*pte) || pte_newpage(*pte)){ | 296 | if(!pte_present(*pte) || pte_newpage(*pte)){ |
297 | updated = 1; | 297 | updated = 1; |
298 | err = os_unmap_memory((void *) addr, | 298 | err = os_unmap_memory((void *) addr, |
299 | PAGE_SIZE); | 299 | PAGE_SIZE); |
300 | if(err < 0) | 300 | if(err < 0) |
301 | panic("munmap failed, errno = %d\n", | 301 | panic("munmap failed, errno = %d\n", |
302 | -err); | 302 | -err); |
303 | if(pte_present(*pte)) | 303 | if(pte_present(*pte)) |
304 | map_memory(addr, | 304 | map_memory(addr, |
305 | pte_val(*pte) & PAGE_MASK, | 305 | pte_val(*pte) & PAGE_MASK, |
306 | PAGE_SIZE, 1, 1, 1); | 306 | PAGE_SIZE, 1, 1, 1); |
307 | } | 307 | } |
308 | else if(pte_newprot(*pte)){ | 308 | else if(pte_newprot(*pte)){ |
309 | updated = 1; | 309 | updated = 1; |
310 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); | 310 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); |
311 | } | 311 | } |
312 | addr += PAGE_SIZE; | 312 | addr += PAGE_SIZE; |
313 | } | 313 | } |
314 | return(updated); | 314 | return(updated); |
315 | } | 315 | } |
316 | 316 | ||
317 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) | 317 | pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) |
318 | { | 318 | { |
319 | return(pgd_offset(mm, address)); | 319 | return(pgd_offset(mm, address)); |
320 | } | 320 | } |
321 | 321 | ||
322 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) | 322 | pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address) |
323 | { | 323 | { |
324 | return(pud_offset(pgd, address)); | 324 | return(pud_offset(pgd, address)); |
325 | } | 325 | } |
326 | 326 | ||
327 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) | 327 | pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address) |
328 | { | 328 | { |
329 | return(pmd_offset(pud, address)); | 329 | return(pmd_offset(pud, address)); |
330 | } | 330 | } |
331 | 331 | ||
332 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) | 332 | pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) |
333 | { | 333 | { |
334 | return(pte_offset_kernel(pmd, address)); | 334 | return(pte_offset_kernel(pmd, address)); |
335 | } | 335 | } |
336 | 336 | ||
337 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) | 337 | pte_t *addr_pte(struct task_struct *task, unsigned long addr) |
338 | { | 338 | { |
339 | pgd_t *pgd = pgd_offset(task->mm, addr); | 339 | pgd_t *pgd = pgd_offset(task->mm, addr); |
340 | pud_t *pud = pud_offset(pgd, addr); | 340 | pud_t *pud = pud_offset(pgd, addr); |
341 | pmd_t *pmd = pmd_offset(pud, addr); | 341 | pmd_t *pmd = pmd_offset(pud, addr); |
342 | 342 | ||
343 | return(pte_offset_map(pmd, addr)); | 343 | return(pte_offset_map(pmd, addr)); |
344 | } | 344 | } |
345 | 345 | ||
346 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) | 346 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) |
347 | { | 347 | { |
348 | address &= PAGE_MASK; | 348 | address &= PAGE_MASK; |
349 | flush_tlb_range(vma, address, address + PAGE_SIZE); | 349 | flush_tlb_range(vma, address, address + PAGE_SIZE); |
350 | } | 350 | } |
351 | 351 | ||
352 | void flush_tlb_all(void) | 352 | void flush_tlb_all(void) |
353 | { | 353 | { |
354 | flush_tlb_mm(current->mm); | 354 | flush_tlb_mm(current->mm); |
355 | } | 355 | } |
356 | 356 | ||
357 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | 357 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) |
358 | { | 358 | { |
359 | CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, | 359 | CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, |
360 | flush_tlb_kernel_range_common, start, end); | 360 | flush_tlb_kernel_range_common, start, end); |
361 | } | 361 | } |
362 | 362 | ||
363 | void flush_tlb_kernel_vm(void) | 363 | void flush_tlb_kernel_vm(void) |
364 | { | 364 | { |
365 | CHOOSE_MODE(flush_tlb_kernel_vm_tt(), | 365 | CHOOSE_MODE(flush_tlb_kernel_vm_tt(), |
366 | flush_tlb_kernel_range_common(start_vm, end_vm)); | 366 | flush_tlb_kernel_range_common(start_vm, end_vm)); |
367 | } | 367 | } |
368 | 368 | ||
369 | void __flush_tlb_one(unsigned long addr) | 369 | void __flush_tlb_one(unsigned long addr) |
370 | { | 370 | { |
371 | CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); | 371 | CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); |
372 | } | 372 | } |
373 | 373 | ||
374 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 374 | void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
375 | unsigned long end) | 375 | unsigned long end) |
376 | { | 376 | { |
377 | CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, | 377 | CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, |
378 | end); | 378 | end); |
379 | } | 379 | } |
380 | 380 | ||
381 | void flush_tlb_mm(struct mm_struct *mm) | 381 | void flush_tlb_mm(struct mm_struct *mm) |
382 | { | 382 | { |
383 | CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); | 383 | CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); |
384 | } | 384 | } |
385 | 385 | ||
386 | void force_flush_all(void) | 386 | void force_flush_all(void) |
387 | { | 387 | { |
388 | CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); | 388 | CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); |
389 | } | 389 | } |
390 | 390 | ||
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index ac70fa5a2e2..e5eeaf2b6af 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -227,9 +227,16 @@ void bad_segv(struct faultinfo fi, unsigned long ip) | |||
227 | 227 | ||
228 | void relay_signal(int sig, union uml_pt_regs *regs) | 228 | void relay_signal(int sig, union uml_pt_regs *regs) |
229 | { | 229 | { |
230 | if(arch_handle_signal(sig, regs)) return; | 230 | if(arch_handle_signal(sig, regs)) |
231 | if(!UPT_IS_USER(regs)) | 231 | return; |
232 | |||
233 | if(!UPT_IS_USER(regs)){ | ||
234 | if(sig == SIGBUS) | ||
235 | printk("Bus error - the /dev/shm or /tmp mount likely " | ||
236 | "just ran out of space\n"); | ||
232 | panic("Kernel mode signal %d", sig); | 237 | panic("Kernel mode signal %d", sig); |
238 | } | ||
239 | |||
233 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); | 240 | current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); |
234 | force_sig(sig, current); | 241 | force_sig(sig, current); |
235 | } | 242 | } |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 6987d1d247a..cd15b9df5b5 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 7555bf9c33d..a97206df5b5 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 90912aaca7a..d1c5670787d 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 560c8063c77..b170b4704dc 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 b98d3ca2cd1..ff203625a4b 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 0ecac563c7b..f6457765b17 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 60e4faedf25..6b81739279d 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 7baf90fda58..42e3d1ed802 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 50314850400..7fe92680c7d 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 b3213613c41..37806621b25 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 516f66dd87e..7cd0369e02b 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 00000000000..0d3eae51835 --- /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 340ef26f594..f67842a7735 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 becd898d939..cb8e8a26328 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 00000000000..3f369e5f976 --- /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 4ae73c0e548..38be096e750 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 90b29ae9af4..1df231a2624 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 865f6a6a259..bbb73a65037 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 c47a2a7ce70..3f5b1514e8a 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 | } |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 6289779ca67..0e32adf03be 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 1 | obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ |
2 | ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \ | 2 | ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ |
3 | sys_call_table.o tls.o | 3 | sys_call_table.o tls.o |
4 | 4 | ||
5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | 5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o |
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c index 41b0ab2fe83..f1bcd399ac9 100644 --- a/arch/um/sys-i386/bugs.c +++ b/arch/um/sys-i386/bugs.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "sysdep/ptrace.h" | 13 | #include "sysdep/ptrace.h" |
14 | #include "task.h" | 14 | #include "task.h" |
15 | #include "os.h" | 15 | #include "os.h" |
16 | #include "user_util.h" | ||
16 | 17 | ||
17 | #define MAXTOKEN 64 | 18 | #define MAXTOKEN 64 |
18 | 19 | ||
@@ -104,17 +105,17 @@ int cpu_feature(char *what, char *buf, int len) | |||
104 | static int check_cpu_flag(char *feature, int *have_it) | 105 | static int check_cpu_flag(char *feature, int *have_it) |
105 | { | 106 | { |
106 | char buf[MAXTOKEN], c; | 107 | char buf[MAXTOKEN], c; |
107 | int fd, len = sizeof(buf)/sizeof(buf[0]); | 108 | int fd, len = ARRAY_SIZE(buf); |
108 | 109 | ||
109 | printk("Checking for host processor %s support...", feature); | 110 | printk("Checking for host processor %s support...", feature); |
110 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); | 111 | fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); |
111 | if(fd < 0){ | 112 | if(fd < 0){ |
112 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); | 113 | printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); |
113 | return(0); | 114 | return 0; |
114 | } | 115 | } |
115 | 116 | ||
116 | *have_it = 0; | 117 | *have_it = 0; |
117 | if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) | 118 | if(!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf))) |
118 | goto out; | 119 | goto out; |
119 | 120 | ||
120 | c = token(fd, buf, len - 1, ' '); | 121 | c = token(fd, buf, len - 1, ' '); |
@@ -138,7 +139,7 @@ static int check_cpu_flag(char *feature, int *have_it) | |||
138 | if(*have_it == 0) printk("No\n"); | 139 | if(*have_it == 0) printk("No\n"); |
139 | else if(*have_it == 1) printk("Yes\n"); | 140 | else if(*have_it == 1) printk("Yes\n"); |
140 | os_close_file(fd); | 141 | os_close_file(fd); |
141 | return(1); | 142 | return 1; |
142 | } | 143 | } |
143 | 144 | ||
144 | #if 0 /* This doesn't work in tt mode, plus it's causing compilation problems | 145 | #if 0 /* This doesn't work in tt mode, plus it's causing compilation problems |
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index fe0877b3509..69971b78bea 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c | |||
@@ -424,9 +424,8 @@ void ldt_get_host_info(void) | |||
424 | size++; | 424 | size++; |
425 | } | 425 | } |
426 | 426 | ||
427 | if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) { | 427 | if(size < ARRAY_SIZE(dummy_list)) |
428 | host_ldt_entries = dummy_list; | 428 | host_ldt_entries = dummy_list; |
429 | } | ||
430 | else { | 429 | else { |
431 | size = (size + 1) * sizeof(dummy_list[0]); | 430 | size = (size + 1) * sizeof(dummy_list[0]); |
432 | host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL); | 431 | host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL); |
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c index 40aa8853144..5f3cc668582 100644 --- a/arch/um/sys-i386/ptrace_user.c +++ b/arch/um/sys-i386/ptrace_user.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "user.h" | 15 | #include "user.h" |
16 | #include "os.h" | 16 | #include "os.h" |
17 | #include "uml-config.h" | 17 | #include "uml-config.h" |
18 | #include "user_util.h" | ||
18 | 19 | ||
19 | int ptrace_getregs(long pid, unsigned long *regs_out) | 20 | int ptrace_getregs(long pid, unsigned long *regs_out) |
20 | { | 21 | { |
@@ -51,7 +52,7 @@ static void write_debugregs(int pid, unsigned long *regs) | |||
51 | int nregs, i; | 52 | int nregs, i; |
52 | 53 | ||
53 | dummy = NULL; | 54 | dummy = NULL; |
54 | nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); | 55 | nregs = ARRAY_SIZE(dummy->u_debugreg); |
55 | for(i = 0; i < nregs; i++){ | 56 | for(i = 0; i < nregs; i++){ |
56 | if((i == 4) || (i == 5)) continue; | 57 | if((i == 4) || (i == 5)) continue; |
57 | if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], | 58 | if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], |
@@ -68,7 +69,7 @@ static void read_debugregs(int pid, unsigned long *regs) | |||
68 | int nregs, i; | 69 | int nregs, i; |
69 | 70 | ||
70 | dummy = NULL; | 71 | dummy = NULL; |
71 | nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); | 72 | nregs = ARRAY_SIZE(dummy->u_debugreg); |
72 | for(i = 0; i < nregs; i++){ | 73 | for(i = 0; i < nregs; i++){ |
73 | regs[i] = ptrace(PTRACE_PEEKUSR, pid, | 74 | regs[i] = ptrace(PTRACE_PEEKUSR, pid, |
74 | &dummy->u_debugreg[i], 0); | 75 | &dummy->u_debugreg[i], 0); |
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S new file mode 100644 index 00000000000..b766792c993 --- /dev/null +++ b/arch/um/sys-i386/setjmp.S | |||
@@ -0,0 +1,58 @@ | |||
1 | # | ||
2 | # arch/i386/setjmp.S | ||
3 | # | ||
4 | # setjmp/longjmp for the i386 architecture | ||
5 | # | ||
6 | |||
7 | # | ||
8 | # The jmp_buf is assumed to contain the following, in order: | ||
9 | # %ebx | ||
10 | # %esp | ||
11 | # %ebp | ||
12 | # %esi | ||
13 | # %edi | ||
14 | # <return address> | ||
15 | # | ||
16 | |||
17 | .text | ||
18 | .align 4 | ||
19 | .globl setjmp | ||
20 | .type setjmp, @function | ||
21 | setjmp: | ||
22 | #ifdef _REGPARM | ||
23 | movl %eax,%edx | ||
24 | #else | ||
25 | movl 4(%esp),%edx | ||
26 | #endif | ||
27 | popl %ecx # Return address, and adjust the stack | ||
28 | xorl %eax,%eax # Return value | ||
29 | movl %ebx,(%edx) | ||
30 | movl %esp,4(%edx) # Post-return %esp! | ||
31 | pushl %ecx # Make the call/return stack happy | ||
32 | movl %ebp,8(%edx) | ||
33 | movl %esi,12(%edx) | ||
34 | movl %edi,16(%edx) | ||
35 | movl %ecx,20(%edx) # Return address | ||
36 | ret | ||
37 | |||
38 | .size setjmp,.-setjmp | ||
39 | |||
40 | .text | ||
41 | .align 4 | ||
42 | .globl longjmp | ||
43 | .type longjmp, @function | ||
44 | longjmp: | ||
45 | #ifdef _REGPARM | ||
46 | xchgl %eax,%edx | ||
47 | #else | ||
48 | movl 4(%esp),%edx # jmp_ptr address | ||
49 | movl 8(%esp),%eax # Return value | ||
50 | #endif | ||
51 | movl (%edx),%ebx | ||
52 | movl 4(%edx),%esp | ||
53 | movl 8(%edx),%ebp | ||
54 | movl 12(%edx),%esi | ||
55 | movl 16(%edx),%edi | ||
56 | jmp *20(%edx) | ||
57 | |||
58 | .size longjmp,.-longjmp | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c19794d435d..f41768b8e25 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | 7 | obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ |
8 | sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \ | 8 | setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ |
9 | tls.o | 9 | ksyms.o tls.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | 11 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o |
12 | obj-$(CONFIG_MODULES) += um_module.o | 12 | obj-$(CONFIG_MODULES) += um_module.o |
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S new file mode 100644 index 00000000000..45f547b4043 --- /dev/null +++ b/arch/um/sys-x86_64/setjmp.S | |||
@@ -0,0 +1,54 @@ | |||
1 | # | ||
2 | # arch/x86_64/setjmp.S | ||
3 | # | ||
4 | # setjmp/longjmp for the x86-64 architecture | ||
5 | # | ||
6 | |||
7 | # | ||
8 | # The jmp_buf is assumed to contain the following, in order: | ||
9 | # %rbx | ||
10 | # %rsp (post-return) | ||
11 | # %rbp | ||
12 | # %r12 | ||
13 | # %r13 | ||
14 | # %r14 | ||
15 | # %r15 | ||
16 | # <return address> | ||
17 | # | ||
18 | |||
19 | .text | ||
20 | .align 4 | ||
21 | .globl setjmp | ||
22 | .type setjmp, @function | ||
23 | setjmp: | ||
24 | pop %rsi # Return address, and adjust the stack | ||
25 | xorl %eax,%eax # Return value | ||
26 | movq %rbx,(%rdi) | ||
27 | movq %rsp,8(%rdi) # Post-return %rsp! | ||
28 | push %rsi # Make the call/return stack happy | ||
29 | movq %rbp,16(%rdi) | ||
30 | movq %r12,24(%rdi) | ||
31 | movq %r13,32(%rdi) | ||
32 | movq %r14,40(%rdi) | ||
33 | movq %r15,48(%rdi) | ||
34 | movq %rsi,56(%rdi) # Return address | ||
35 | ret | ||
36 | |||
37 | .size setjmp,.-setjmp | ||
38 | |||
39 | .text | ||
40 | .align 4 | ||
41 | .globl longjmp | ||
42 | .type longjmp, @function | ||
43 | longjmp: | ||
44 | movl %esi,%eax # Return value (int) | ||
45 | movq (%rdi),%rbx | ||
46 | movq 8(%rdi),%rsp | ||
47 | movq 16(%rdi),%rbp | ||
48 | movq 24(%rdi),%r12 | ||
49 | movq 32(%rdi),%r13 | ||
50 | movq 40(%rdi),%r14 | ||
51 | movq 48(%rdi),%r15 | ||
52 | jmp *56(%rdi) | ||
53 | |||
54 | .size longjmp,.-longjmp | ||