diff options
-rw-r--r-- | arch/um/include/os.h | 1 | ||||
-rw-r--r-- | arch/um/include/sigio.h | 1 | ||||
-rw-r--r-- | arch/um/kernel/sigio_kern.c | 10 | ||||
-rw-r--r-- | arch/um/kernel/sigio_user.c | 162 | ||||
-rw-r--r-- | arch/um/kernel/um_arch.c | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 128 |
6 files changed, 148 insertions, 157 deletions
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index efae3e6acb5b..6d865d4eade0 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -161,6 +161,7 @@ extern int os_lock_file(int fd, int excl); | |||
161 | /* start_up.c */ | 161 | /* start_up.c */ |
162 | extern void os_early_checks(void); | 162 | extern void os_early_checks(void); |
163 | extern int can_do_skas(void); | 163 | extern int can_do_skas(void); |
164 | extern void os_check_bugs(void); | ||
164 | 165 | ||
165 | /* Make sure they are clear when running in TT mode. Required by | 166 | /* Make sure they are clear when running in TT mode. Required by |
166 | * SEGV_MAYBE_FIXABLE */ | 167 | * SEGV_MAYBE_FIXABLE */ |
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h index 37d76e29a147..1432fcfb3212 100644 --- a/arch/um/include/sigio.h +++ b/arch/um/include/sigio.h | |||
@@ -8,7 +8,6 @@ | |||
8 | 8 | ||
9 | extern int write_sigio_irq(int fd); | 9 | extern int write_sigio_irq(int fd); |
10 | extern int register_sigio_fd(int fd); | 10 | extern int register_sigio_fd(int fd); |
11 | extern int read_sigio_fd(int fd); | ||
12 | extern int add_sigio_fd(int fd, int read); | 11 | extern int add_sigio_fd(int fd, int read); |
13 | extern int ignore_sigio_fd(int fd); | 12 | extern int ignore_sigio_fd(int fd); |
14 | extern void sigio_lock(void); | 13 | extern void sigio_lock(void); |
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c index 229988463c4c..1c1300fb1e95 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio_kern.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -12,13 +12,16 @@ | |||
12 | #include "sigio.h" | 12 | #include "sigio.h" |
13 | #include "irq_user.h" | 13 | #include "irq_user.h" |
14 | #include "irq_kern.h" | 14 | #include "irq_kern.h" |
15 | #include "os.h" | ||
15 | 16 | ||
16 | /* Protected by sigio_lock() called from write_sigio_workaround */ | 17 | /* Protected by sigio_lock() called from write_sigio_workaround */ |
17 | static int sigio_irq_fd = -1; | 18 | static int sigio_irq_fd = -1; |
18 | 19 | ||
19 | static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) | 20 | static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) |
20 | { | 21 | { |
21 | read_sigio_fd(sigio_irq_fd); | 22 | char c; |
23 | |||
24 | os_read_file(sigio_irq_fd, &c, sizeof(c)); | ||
22 | reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); | 25 | reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); |
23 | return(IRQ_HANDLED); | 26 | return(IRQ_HANDLED); |
24 | } | 27 | } |
@@ -51,6 +54,9 @@ void sigio_unlock(void) | |||
51 | spin_unlock(&sigio_spinlock); | 54 | spin_unlock(&sigio_spinlock); |
52 | } | 55 | } |
53 | 56 | ||
57 | extern void sigio_cleanup(void); | ||
58 | __uml_exitcall(sigio_cleanup); | ||
59 | |||
54 | /* | 60 | /* |
55 | * Overrides for Emacs so that we follow Linus's tabbing style. | 61 | * Overrides for Emacs so that we follow Linus's tabbing style. |
56 | * Emacs will notice this stuff at the end of the file and automatically | 62 | * Emacs will notice this stuff at the end of the file and automatically |
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index f7b18e157d35..9bef9413cb5d 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -20,127 +20,6 @@ | |||
20 | #include "sigio.h" | 20 | #include "sigio.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | 22 | ||
23 | /* Changed during early boot */ | ||
24 | int pty_output_sigio = 0; | ||
25 | int pty_close_sigio = 0; | ||
26 | |||
27 | /* Used as a flag during SIGIO testing early in boot */ | ||
28 | static volatile int got_sigio = 0; | ||
29 | |||
30 | void __init handler(int sig) | ||
31 | { | ||
32 | got_sigio = 1; | ||
33 | } | ||
34 | |||
35 | struct openpty_arg { | ||
36 | int master; | ||
37 | int slave; | ||
38 | int err; | ||
39 | }; | ||
40 | |||
41 | static void openpty_cb(void *arg) | ||
42 | { | ||
43 | struct openpty_arg *info = arg; | ||
44 | |||
45 | info->err = 0; | ||
46 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
47 | info->err = -errno; | ||
48 | } | ||
49 | |||
50 | void __init check_one_sigio(void (*proc)(int, int)) | ||
51 | { | ||
52 | struct sigaction old, new; | ||
53 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
54 | int master, slave, err; | ||
55 | |||
56 | initial_thread_cb(openpty_cb, &pty); | ||
57 | if(pty.err){ | ||
58 | printk("openpty failed, errno = %d\n", -pty.err); | ||
59 | return; | ||
60 | } | ||
61 | |||
62 | master = pty.master; | ||
63 | slave = pty.slave; | ||
64 | |||
65 | if((master == -1) || (slave == -1)){ | ||
66 | printk("openpty failed to allocate a pty\n"); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | /* Not now, but complain so we now where we failed. */ | ||
71 | err = raw(master); | ||
72 | if (err < 0) | ||
73 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
74 | |||
75 | err = os_sigio_async(master, slave); | ||
76 | if(err < 0) | ||
77 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
78 | |||
79 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
80 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
81 | new = old; | ||
82 | new.sa_handler = handler; | ||
83 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
84 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
85 | |||
86 | got_sigio = 0; | ||
87 | (*proc)(master, slave); | ||
88 | |||
89 | os_close_file(master); | ||
90 | os_close_file(slave); | ||
91 | |||
92 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
93 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
94 | } | ||
95 | |||
96 | static void tty_output(int master, int slave) | ||
97 | { | ||
98 | int n; | ||
99 | char buf[512]; | ||
100 | |||
101 | printk("Checking that host ptys support output SIGIO..."); | ||
102 | |||
103 | memset(buf, 0, sizeof(buf)); | ||
104 | |||
105 | while(os_write_file(master, buf, sizeof(buf)) > 0) ; | ||
106 | if(errno != EAGAIN) | ||
107 | panic("check_sigio : write failed, errno = %d\n", errno); | ||
108 | while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
109 | |||
110 | if (got_sigio) { | ||
111 | printk("Yes\n"); | ||
112 | pty_output_sigio = 1; | ||
113 | } else if (n == -EAGAIN) { | ||
114 | printk("No, enabling workaround\n"); | ||
115 | } else { | ||
116 | panic("check_sigio : read failed, err = %d\n", n); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static void tty_close(int master, int slave) | ||
121 | { | ||
122 | printk("Checking that host ptys support SIGIO on close..."); | ||
123 | |||
124 | os_close_file(slave); | ||
125 | if(got_sigio){ | ||
126 | printk("Yes\n"); | ||
127 | pty_close_sigio = 1; | ||
128 | } | ||
129 | else printk("No, enabling workaround\n"); | ||
130 | } | ||
131 | |||
132 | void __init check_sigio(void) | ||
133 | { | ||
134 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
135 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
136 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
137 | "check\n"); | ||
138 | return; | ||
139 | } | ||
140 | check_one_sigio(tty_output); | ||
141 | check_one_sigio(tty_close); | ||
142 | } | ||
143 | |||
144 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an | 23 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an |
145 | * exitcall. | 24 | * exitcall. |
146 | */ | 25 | */ |
@@ -267,10 +146,10 @@ static void update_thread(void) | |||
267 | if(write_sigio_pid != -1) | 146 | if(write_sigio_pid != -1) |
268 | os_kill_process(write_sigio_pid, 1); | 147 | os_kill_process(write_sigio_pid, 1); |
269 | write_sigio_pid = -1; | 148 | write_sigio_pid = -1; |
270 | os_close_file(sigio_private[0]); | 149 | close(sigio_private[0]); |
271 | os_close_file(sigio_private[1]); | 150 | close(sigio_private[1]); |
272 | os_close_file(write_sigio_fds[0]); | 151 | close(write_sigio_fds[0]); |
273 | os_close_file(write_sigio_fds[1]); | 152 | close(write_sigio_fds[1]); |
274 | /* Critical section end */ | 153 | /* Critical section end */ |
275 | set_signals(flags); | 154 | set_signals(flags); |
276 | } | 155 | } |
@@ -428,39 +307,18 @@ void write_sigio_workaround(void) | |||
428 | out_free: | 307 | out_free: |
429 | kfree(p); | 308 | kfree(p); |
430 | out_close2: | 309 | out_close2: |
431 | os_close_file(l_sigio_private[0]); | 310 | close(l_sigio_private[0]); |
432 | os_close_file(l_sigio_private[1]); | 311 | close(l_sigio_private[1]); |
433 | out_close1: | 312 | out_close1: |
434 | os_close_file(l_write_sigio_fds[0]); | 313 | close(l_write_sigio_fds[0]); |
435 | os_close_file(l_write_sigio_fds[1]); | 314 | close(l_write_sigio_fds[1]); |
436 | return; | 315 | return; |
437 | } | 316 | } |
438 | 317 | ||
439 | int read_sigio_fd(int fd) | 318 | void sigio_cleanup(void) |
440 | { | ||
441 | int n; | ||
442 | char c; | ||
443 | |||
444 | n = os_read_file(fd, &c, sizeof(c)); | ||
445 | if(n != sizeof(c)){ | ||
446 | if(n < 0) { | ||
447 | printk("read_sigio_fd - read failed, err = %d\n", -n); | ||
448 | return(n); | ||
449 | } | ||
450 | else { | ||
451 | printk("read_sigio_fd - short read, bytes = %d\n", n); | ||
452 | return(-EIO); | ||
453 | } | ||
454 | } | ||
455 | return(n); | ||
456 | } | ||
457 | |||
458 | static void sigio_cleanup(void) | ||
459 | { | 319 | { |
460 | if (write_sigio_pid != -1) { | 320 | if (write_sigio_pid != -1) { |
461 | os_kill_process(write_sigio_pid, 1); | 321 | os_kill_process(write_sigio_pid, 1); |
462 | write_sigio_pid = -1; | 322 | write_sigio_pid = -1; |
463 | } | 323 | } |
464 | } | 324 | } |
465 | |||
466 | __uml_exitcall(sigio_cleanup); | ||
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 0c5b9dcfbe2e..bb1c87211ac1 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -487,8 +487,7 @@ void __init setup_arch(char **cmdline_p) | |||
487 | void __init check_bugs(void) | 487 | void __init check_bugs(void) |
488 | { | 488 | { |
489 | arch_check_bugs(); | 489 | arch_check_bugs(); |
490 | check_sigio(); | 490 | os_check_bugs(); |
491 | check_devanon(); | ||
492 | } | 491 | } |
493 | 492 | ||
494 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) | 493 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 829d6b0d8b02..32753131f8d8 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <pty.h> | ||
6 | #include <stdio.h> | 7 | #include <stdio.h> |
7 | #include <stddef.h> | 8 | #include <stddef.h> |
8 | #include <stdarg.h> | 9 | #include <stdarg.h> |
@@ -539,3 +540,130 @@ int __init parse_iomem(char *str, int *add) | |||
539 | return(1); | 540 | return(1); |
540 | } | 541 | } |
541 | 542 | ||
543 | |||
544 | /* Changed during early boot */ | ||
545 | int pty_output_sigio = 0; | ||
546 | int pty_close_sigio = 0; | ||
547 | |||
548 | /* Used as a flag during SIGIO testing early in boot */ | ||
549 | static volatile int got_sigio = 0; | ||
550 | |||
551 | static void __init handler(int sig) | ||
552 | { | ||
553 | got_sigio = 1; | ||
554 | } | ||
555 | |||
556 | struct openpty_arg { | ||
557 | int master; | ||
558 | int slave; | ||
559 | int err; | ||
560 | }; | ||
561 | |||
562 | static void openpty_cb(void *arg) | ||
563 | { | ||
564 | struct openpty_arg *info = arg; | ||
565 | |||
566 | info->err = 0; | ||
567 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
568 | info->err = -errno; | ||
569 | } | ||
570 | |||
571 | static void __init check_one_sigio(void (*proc)(int, int)) | ||
572 | { | ||
573 | struct sigaction old, new; | ||
574 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
575 | int master, slave, err; | ||
576 | |||
577 | initial_thread_cb(openpty_cb, &pty); | ||
578 | if(pty.err){ | ||
579 | printk("openpty failed, errno = %d\n", -pty.err); | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | master = pty.master; | ||
584 | slave = pty.slave; | ||
585 | |||
586 | if((master == -1) || (slave == -1)){ | ||
587 | printk("openpty failed to allocate a pty\n"); | ||
588 | return; | ||
589 | } | ||
590 | |||
591 | /* Not now, but complain so we now where we failed. */ | ||
592 | err = raw(master); | ||
593 | if (err < 0) | ||
594 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
595 | |||
596 | err = os_sigio_async(master, slave); | ||
597 | if(err < 0) | ||
598 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
599 | |||
600 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
601 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
602 | new = old; | ||
603 | new.sa_handler = handler; | ||
604 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
605 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
606 | |||
607 | got_sigio = 0; | ||
608 | (*proc)(master, slave); | ||
609 | |||
610 | close(master); | ||
611 | close(slave); | ||
612 | |||
613 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
614 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
615 | } | ||
616 | |||
617 | static void tty_output(int master, int slave) | ||
618 | { | ||
619 | int n; | ||
620 | char buf[512]; | ||
621 | |||
622 | printk("Checking that host ptys support output SIGIO..."); | ||
623 | |||
624 | memset(buf, 0, sizeof(buf)); | ||
625 | |||
626 | while(os_write_file(master, buf, sizeof(buf)) > 0) ; | ||
627 | if(errno != EAGAIN) | ||
628 | panic("check_sigio : write failed, errno = %d\n", errno); | ||
629 | while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
630 | |||
631 | if(got_sigio){ | ||
632 | printk("Yes\n"); | ||
633 | pty_output_sigio = 1; | ||
634 | } | ||
635 | else if(n == -EAGAIN) printk("No, enabling workaround\n"); | ||
636 | else panic("check_sigio : read failed, err = %d\n", n); | ||
637 | } | ||
638 | |||
639 | static void tty_close(int master, int slave) | ||
640 | { | ||
641 | printk("Checking that host ptys support SIGIO on close..."); | ||
642 | |||
643 | close(slave); | ||
644 | if(got_sigio){ | ||
645 | printk("Yes\n"); | ||
646 | pty_close_sigio = 1; | ||
647 | } | ||
648 | else printk("No, enabling workaround\n"); | ||
649 | } | ||
650 | |||
651 | void __init check_sigio(void) | ||
652 | { | ||
653 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
654 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
655 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
656 | "check\n"); | ||
657 | return; | ||
658 | } | ||
659 | check_one_sigio(tty_output); | ||
660 | check_one_sigio(tty_close); | ||
661 | } | ||
662 | |||
663 | void os_check_bugs(void) | ||
664 | { | ||
665 | check_ptrace(); | ||
666 | check_sigio(); | ||
667 | check_devanon(); | ||
668 | } | ||
669 | |||