aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig3
-rw-r--r--arch/um/drivers/chan_kern.c103
-rw-r--r--arch/um/drivers/harddog_kern.c58
-rw-r--r--arch/um/drivers/harddog_user.c23
-rw-r--r--arch/um/drivers/hostaudio_kern.c169
-rw-r--r--arch/um/drivers/line.c209
-rw-r--r--arch/um/drivers/mconsole_kern.c62
-rw-r--r--arch/um/drivers/mconsole_user.c2
-rw-r--r--arch/um/drivers/net_kern.c172
-rw-r--r--arch/um/drivers/port_kern.c50
-rw-r--r--arch/um/drivers/port_user.c51
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/ssl.c44
-rw-r--r--arch/um/drivers/stdio_console.c51
-rw-r--r--arch/um/drivers/ubd_kern.c231
-rw-r--r--arch/um/include/chan_kern.h5
-rw-r--r--arch/um/include/chan_user.h21
-rw-r--r--arch/um/include/kern_util.h5
-rw-r--r--arch/um/include/line.h57
-rw-r--r--arch/um/include/mconsole_kern.h17
-rw-r--r--arch/um/include/net_kern.h14
-rw-r--r--arch/um/include/os.h3
-rw-r--r--arch/um/include/sigio.h11
-rw-r--r--arch/um/include/tempfile.h10
-rw-r--r--arch/um/include/umid.h22
-rw-r--r--arch/um/include/user_util.h2
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/exec.c2
-rw-r--r--arch/um/kernel/irq.c7
-rw-r--r--arch/um/kernel/mem.c90
-rw-r--r--arch/um/kernel/physmem.c74
-rw-r--r--arch/um/kernel/ptrace.c7
-rw-r--r--arch/um/kernel/resource.c23
-rw-r--r--arch/um/kernel/sigio.c7
-rw-r--r--arch/um/kernel/skas/mem.c6
-rw-r--r--arch/um/kernel/syscall.c16
-rw-r--r--arch/um/kernel/sysrq.c2
-rw-r--r--arch/um/kernel/time.c24
-rw-r--r--arch/um/kernel/trap.c28
-rw-r--r--arch/um/kernel/tt/gdb.c4
-rw-r--r--arch/um/kernel/tt/gdb_kern.c5
-rw-r--r--arch/um/kernel/um_arch.c9
-rw-r--r--arch/um/kernel/umid.c4
-rw-r--r--arch/um/os-Linux/aio.c16
-rw-r--r--arch/um/os-Linux/elf_aux.c3
-rw-r--r--arch/um/os-Linux/file.c19
-rw-r--r--arch/um/os-Linux/irq.c6
-rw-r--r--arch/um/os-Linux/mem.c16
-rw-r--r--arch/um/os-Linux/start_up.c207
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c14
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/prctl.c12
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c6
-rw-r--r--arch/um/os-Linux/umid.c3
-rw-r--r--arch/um/sys-x86_64/ptrace.c5
-rw-r--r--arch/um/sys-x86_64/syscalls.c75
-rw-r--r--arch/um/sys-x86_64/tls.c11
57 files changed, 1055 insertions, 1046 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index d32a80e6668c..b3a21ba77cd2 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -16,6 +16,9 @@ config MMU
16 bool 16 bool
17 default y 17 default y
18 18
19config NO_IOMEM
20 def_bool y
21
19mainmenu "Linux/Usermode Kernel Configuration" 22mainmenu "Linux/Usermode Kernel Configuration"
20 23
21config ISA 24config ISA
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 7d4190e55654..7b8baf146acc 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -19,44 +19,11 @@
19#include "line.h" 19#include "line.h"
20#include "os.h" 20#include "os.h"
21 21
22/* XXX: could well be moved to somewhere else, if needed. */
23static int my_printf(const char * fmt, ...)
24 __attribute__ ((format (printf, 1, 2)));
25
26static int my_printf(const char * fmt, ...)
27{
28 /* Yes, can be called on atomic context.*/
29 char *buf = kmalloc(4096, GFP_ATOMIC);
30 va_list args;
31 int r;
32
33 if (!buf) {
34 /* We print directly fmt.
35 * Yes, yes, yes, feel free to complain. */
36 r = strlen(fmt);
37 } else {
38 va_start(args, fmt);
39 r = vsprintf(buf, fmt, args);
40 va_end(args);
41 fmt = buf;
42 }
43
44 if (r)
45 r = os_write_file(1, fmt, r);
46 return r;
47
48}
49
50#ifdef CONFIG_NOCONFIG_CHAN 22#ifdef CONFIG_NOCONFIG_CHAN
51/* Despite its name, there's no added trailing newline. */ 23static void *not_configged_init(char *str, int device,
52static int my_puts(const char * buf) 24 const struct chan_opts *opts)
53{
54 return os_write_file(1, buf, strlen(buf));
55}
56
57static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 25{
59 my_puts("Using a channel type which is configured out of " 26 printk("Using a channel type which is configured out of "
60 "UML\n"); 27 "UML\n");
61 return NULL; 28 return NULL;
62} 29}
@@ -64,34 +31,34 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
64static int not_configged_open(int input, int output, int primary, void *data, 31static int not_configged_open(int input, int output, int primary, void *data,
65 char **dev_out) 32 char **dev_out)
66{ 33{
67 my_puts("Using a channel type which is configured out of " 34 printk("Using a channel type which is configured out of "
68 "UML\n"); 35 "UML\n");
69 return -ENODEV; 36 return -ENODEV;
70} 37}
71 38
72static void not_configged_close(int fd, void *data) 39static void not_configged_close(int fd, void *data)
73{ 40{
74 my_puts("Using a channel type which is configured out of " 41 printk("Using a channel type which is configured out of "
75 "UML\n"); 42 "UML\n");
76} 43}
77 44
78static int not_configged_read(int fd, char *c_out, void *data) 45static int not_configged_read(int fd, char *c_out, void *data)
79{ 46{
80 my_puts("Using a channel type which is configured out of " 47 printk("Using a channel type which is configured out of "
81 "UML\n"); 48 "UML\n");
82 return -EIO; 49 return -EIO;
83} 50}
84 51
85static int not_configged_write(int fd, const char *buf, int len, void *data) 52static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 53{
87 my_puts("Using a channel type which is configured out of " 54 printk("Using a channel type which is configured out of "
88 "UML\n"); 55 "UML\n");
89 return -EIO; 56 return -EIO;
90} 57}
91 58
92static int not_configged_console_write(int fd, const char *buf, int len) 59static int not_configged_console_write(int fd, const char *buf, int len)
93{ 60{
94 my_puts("Using a channel type which is configured out of " 61 printk("Using a channel type which is configured out of "
95 "UML\n"); 62 "UML\n");
96 return -EIO; 63 return -EIO;
97} 64}
@@ -99,14 +66,14 @@ static int not_configged_console_write(int fd, const char *buf, int len)
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 66static int not_configged_window_size(int fd, void *data, unsigned short *rows,
100 unsigned short *cols) 67 unsigned short *cols)
101{ 68{
102 my_puts("Using a channel type which is configured out of " 69 printk("Using a channel type which is configured out of "
103 "UML\n"); 70 "UML\n");
104 return -ENODEV; 71 return -ENODEV;
105} 72}
106 73
107static void not_configged_free(void *data) 74static void not_configged_free(void *data)
108{ 75{
109 my_puts("Using a channel type which is configured out of " 76 printk("Using a channel type which is configured out of "
110 "UML\n"); 77 "UML\n");
111} 78}
112 79
@@ -255,15 +222,28 @@ void enable_chan(struct line *line)
255 } 222 }
256} 223}
257 224
225/* Items are added in IRQ context, when free_irq can't be called, and
226 * removed in process context, when it can.
227 * This handles interrupt sources which disappear, and which need to
228 * be permanently disabled. This is discovered in IRQ context, but
229 * the freeing of the IRQ must be done later.
230 */
231static DEFINE_SPINLOCK(irqs_to_free_lock);
258static LIST_HEAD(irqs_to_free); 232static LIST_HEAD(irqs_to_free);
259 233
260void free_irqs(void) 234void free_irqs(void)
261{ 235{
262 struct chan *chan; 236 struct chan *chan;
237 LIST_HEAD(list);
238 struct list_head *ele;
263 239
264 while(!list_empty(&irqs_to_free)){ 240 spin_lock_irq(&irqs_to_free_lock);
265 chan = list_entry(irqs_to_free.next, struct chan, free_list); 241 list_splice_init(&irqs_to_free, &list);
266 list_del(&chan->free_list); 242 INIT_LIST_HEAD(&irqs_to_free);
243 spin_unlock_irq(&irqs_to_free_lock);
244
245 list_for_each(ele, &list){
246 chan = list_entry(ele, struct chan, free_list);
267 247
268 if(chan->input) 248 if(chan->input)
269 free_irq(chan->line->driver->read_irq, chan); 249 free_irq(chan->line->driver->read_irq, chan);
@@ -279,7 +259,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq)
279 return; 259 return;
280 260
281 if(delay_free_irq){ 261 if(delay_free_irq){
262 spin_lock_irq(&irqs_to_free_lock);
282 list_add(&chan->free_list, &irqs_to_free); 263 list_add(&chan->free_list, &irqs_to_free);
264 spin_unlock_irq(&irqs_to_free_lock);
283 } 265 }
284 else { 266 else {
285 if(chan->input) 267 if(chan->input)
@@ -372,8 +354,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
372 return ret; 354 return ret;
373} 355}
374 356
375int console_open_chan(struct line *line, struct console *co, 357int console_open_chan(struct line *line, struct console *co)
376 const struct chan_opts *opts)
377{ 358{
378 int err; 359 int err;
379 360
@@ -381,7 +362,7 @@ int console_open_chan(struct line *line, struct console *co,
381 if(err) 362 if(err)
382 return err; 363 return err;
383 364
384 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 365 printk("Console initialized on /dev/%s%d\n", co->name, co->index);
385 return 0; 366 return 0;
386} 367}
387 368
@@ -534,7 +515,7 @@ static const struct chan_type chan_table[] = {
534}; 515};
535 516
536static struct chan *parse_chan(struct line *line, char *str, int device, 517static struct chan *parse_chan(struct line *line, char *str, int device,
537 const struct chan_opts *opts) 518 const struct chan_opts *opts, char **error_out)
538{ 519{
539 const struct chan_type *entry; 520 const struct chan_type *entry;
540 const struct chan_ops *ops; 521 const struct chan_ops *ops;
@@ -553,19 +534,21 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
553 } 534 }
554 } 535 }
555 if(ops == NULL){ 536 if(ops == NULL){
556 my_printf("parse_chan couldn't parse \"%s\"\n", 537 *error_out = "No match for configured backends";
557 str);
558 return NULL; 538 return NULL;
559 } 539 }
560 if(ops->init == NULL) 540
561 return NULL;
562 data = (*ops->init)(str, device, opts); 541 data = (*ops->init)(str, device, opts);
563 if(data == NULL) 542 if(data == NULL){
543 *error_out = "Configuration failed";
564 return NULL; 544 return NULL;
545 }
565 546
566 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 547 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
567 if(chan == NULL) 548 if(chan == NULL){
549 *error_out = "Memory allocation failed";
568 return NULL; 550 return NULL;
551 }
569 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 552 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
570 .free_list = 553 .free_list =
571 LIST_HEAD_INIT(chan->free_list), 554 LIST_HEAD_INIT(chan->free_list),
@@ -582,7 +565,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
582} 565}
583 566
584int parse_chan_pair(char *str, struct line *line, int device, 567int parse_chan_pair(char *str, struct line *line, int device,
585 const struct chan_opts *opts) 568 const struct chan_opts *opts, char **error_out)
586{ 569{
587 struct list_head *chans = &line->chan_list; 570 struct list_head *chans = &line->chan_list;
588 struct chan *new, *chan; 571 struct chan *new, *chan;
@@ -599,14 +582,14 @@ int parse_chan_pair(char *str, struct line *line, int device,
599 in = str; 582 in = str;
600 *out = '\0'; 583 *out = '\0';
601 out++; 584 out++;
602 new = parse_chan(line, in, device, opts); 585 new = parse_chan(line, in, device, opts, error_out);
603 if(new == NULL) 586 if(new == NULL)
604 return -1; 587 return -1;
605 588
606 new->input = 1; 589 new->input = 1;
607 list_add(&new->list, chans); 590 list_add(&new->list, chans);
608 591
609 new = parse_chan(line, out, device, opts); 592 new = parse_chan(line, out, device, opts, error_out);
610 if(new == NULL) 593 if(new == NULL)
611 return -1; 594 return -1;
612 595
@@ -614,7 +597,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
614 new->output = 1; 597 new->output = 1;
615 } 598 }
616 else { 599 else {
617 new = parse_chan(line, str, device, opts); 600 new = parse_chan(line, str, device, opts, error_out);
618 if(new == NULL) 601 if(new == NULL)
619 return -1; 602 return -1;
620 603
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 64ff22aa077b..55601687b3bc 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -9,10 +9,10 @@
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version. 11 * 2 of the License, or (at your option) any later version.
12 * 12 *
13 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 13 * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
14 * warranty for any of this software. This material is provided 14 * warranty for any of this software. This material is provided
15 * "AS-IS" and at no charge. 15 * "AS-IS" and at no charge.
16 * 16 *
17 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> 17 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
18 * 18 *
@@ -29,11 +29,11 @@
29 * Made SMP safe for 2.3.x 29 * Made SMP safe for 2.3.x
30 * 30 *
31 * 20011127 Joel Becker (jlbec@evilplan.org> 31 * 20011127 Joel Becker (jlbec@evilplan.org>
32 * Added soft_noboot; Allows testing the softdog trigger without 32 * Added soft_noboot; Allows testing the softdog trigger without
33 * requiring a recompile. 33 * requiring a recompile.
34 * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. 34 * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
35 */ 35 */
36 36
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/types.h> 38#include <linux/types.h>
39#include <linux/kernel.h> 39#include <linux/kernel.h>
@@ -44,12 +44,13 @@
44#include <linux/reboot.h> 44#include <linux/reboot.h>
45#include <linux/smp_lock.h> 45#include <linux/smp_lock.h>
46#include <linux/init.h> 46#include <linux/init.h>
47#include <linux/spinlock.h>
47#include <asm/uaccess.h> 48#include <asm/uaccess.h>
48#include "mconsole.h" 49#include "mconsole.h"
49 50
50MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
51 52
52/* Locked by the BKL in harddog_open and harddog_release */ 53static DEFINE_SPINLOCK(lock);
53static int timer_alive; 54static int timer_alive;
54static int harddog_in_fd = -1; 55static int harddog_in_fd = -1;
55static int harddog_out_fd = -1; 56static int harddog_out_fd = -1;
@@ -57,18 +58,18 @@ static int harddog_out_fd = -1;
57/* 58/*
58 * Allow only one person to hold it open 59 * Allow only one person to hold it open
59 */ 60 */
60 61
61extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); 62extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock);
62 63
63static int harddog_open(struct inode *inode, struct file *file) 64static int harddog_open(struct inode *inode, struct file *file)
64{ 65{
65 int err; 66 int err = -EBUSY;
66 char *sock = NULL; 67 char *sock = NULL;
67 68
68 lock_kernel(); 69 spin_lock(&lock);
69 if(timer_alive) 70 if(timer_alive)
70 return -EBUSY; 71 goto err;
71#ifdef CONFIG_HARDDOG_NOWAYOUT 72#ifdef CONFIG_HARDDOG_NOWAYOUT
72 __module_get(THIS_MODULE); 73 __module_get(THIS_MODULE);
73#endif 74#endif
74 75
@@ -76,11 +77,15 @@ static int harddog_open(struct inode *inode, struct file *file)
76 sock = mconsole_notify_socket(); 77 sock = mconsole_notify_socket();
77#endif 78#endif
78 err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock); 79 err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock);
79 if(err) return(err); 80 if(err)
81 goto err;
80 82
81 timer_alive = 1; 83 timer_alive = 1;
82 unlock_kernel(); 84 spin_unlock(&lock);
83 return nonseekable_open(inode, file); 85 return nonseekable_open(inode, file);
86err:
87 spin_unlock(&lock);
88 return err;
84} 89}
85 90
86extern void stop_watchdog(int in_fd, int out_fd); 91extern void stop_watchdog(int in_fd, int out_fd);
@@ -90,14 +95,16 @@ static int harddog_release(struct inode *inode, struct file *file)
90 /* 95 /*
91 * Shut off the timer. 96 * Shut off the timer.
92 */ 97 */
93 lock_kernel(); 98
99 spin_lock(&lock);
94 100
95 stop_watchdog(harddog_in_fd, harddog_out_fd); 101 stop_watchdog(harddog_in_fd, harddog_out_fd);
96 harddog_in_fd = -1; 102 harddog_in_fd = -1;
97 harddog_out_fd = -1; 103 harddog_out_fd = -1;
98 104
99 timer_alive=0; 105 timer_alive=0;
100 unlock_kernel(); 106 spin_unlock(&lock);
107
101 return 0; 108 return 0;
102} 109}
103 110
@@ -110,7 +117,7 @@ static ssize_t harddog_write(struct file *file, const char __user *data, size_t
110 * Refresh the timer. 117 * Refresh the timer.
111 */ 118 */
112 if(len) 119 if(len)
113 return(ping_watchdog(harddog_out_fd)); 120 return ping_watchdog(harddog_out_fd);
114 return 0; 121 return 0;
115} 122}
116 123
@@ -134,11 +141,11 @@ static int harddog_ioctl(struct inode *inode, struct file *file,
134 case WDIOC_GETBOOTSTATUS: 141 case WDIOC_GETBOOTSTATUS:
135 return put_user(0,(int __user *)argp); 142 return put_user(0,(int __user *)argp);
136 case WDIOC_KEEPALIVE: 143 case WDIOC_KEEPALIVE:
137 return(ping_watchdog(harddog_out_fd)); 144 return ping_watchdog(harddog_out_fd);
138 } 145 }
139} 146}
140 147
141static struct file_operations harddog_fops = { 148static const struct file_operations harddog_fops = {
142 .owner = THIS_MODULE, 149 .owner = THIS_MODULE,
143 .write = harddog_write, 150 .write = harddog_write,
144 .ioctl = harddog_ioctl, 151 .ioctl = harddog_ioctl,
@@ -165,7 +172,7 @@ static int __init harddog_init(void)
165 172
166 printk(banner); 173 printk(banner);
167 174
168 return(0); 175 return 0;
169} 176}
170 177
171static void __exit harddog_exit(void) 178static void __exit harddog_exit(void)
@@ -175,14 +182,3 @@ static void __exit harddog_exit(void)
175 182
176module_init(harddog_init); 183module_init(harddog_init);
177module_exit(harddog_exit); 184module_exit(harddog_exit);
178
179/*
180 * Overrides for Emacs so that we follow Linus's tabbing style.
181 * Emacs will notice this stuff at the end of the file and automatically
182 * adjust the settings for this buffer only. This must remain at the end
183 * of the file.
184 * ---------------------------------------------------------------------------
185 * Local variables:
186 * c-file-style: "linux"
187 * End:
188 */
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index def013b5a3c7..c495ecf263b1 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_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 */
@@ -38,7 +38,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
38 int in_fds[2], out_fds[2], pid, n, err; 38 int in_fds[2], out_fds[2], pid, n, err;
39 char pid_buf[sizeof("nnnnn\0")], c; 39 char pid_buf[sizeof("nnnnn\0")], c;
40 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; 40 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
41 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, 41 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
42 NULL }; 42 NULL };
43 char **args = NULL; 43 char **args = NULL;
44 44
@@ -96,7 +96,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
96 } 96 }
97 *in_fd_ret = in_fds[0]; 97 *in_fd_ret = in_fds[0];
98 *out_fd_ret = out_fds[1]; 98 *out_fd_ret = out_fds[1];
99 return(0); 99 return 0;
100 100
101 out_close_in: 101 out_close_in:
102 os_close_file(in_fds[0]); 102 os_close_file(in_fds[0]);
@@ -105,7 +105,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
105 os_close_file(out_fds[0]); 105 os_close_file(out_fds[0]);
106 os_close_file(out_fds[1]); 106 os_close_file(out_fds[1]);
107 out: 107 out:
108 return(err); 108 return err;
109} 109}
110 110
111void stop_watchdog(int in_fd, int out_fd) 111void stop_watchdog(int in_fd, int out_fd)
@@ -123,20 +123,9 @@ int ping_watchdog(int fd)
123 if(n != sizeof(c)){ 123 if(n != sizeof(c)){
124 printk("ping_watchdog - write failed, err = %d\n", -n); 124 printk("ping_watchdog - write failed, err = %d\n", -n);
125 if(n < 0) 125 if(n < 0)
126 return(n); 126 return n;
127 return(-EIO); 127 return -EIO;
128 } 128 }
129 return 1; 129 return 1;
130 130
131} 131}
132
133/*
134 * Overrides for Emacs so that we follow Linus's tabbing style.
135 * Emacs will notice this stuff at the end of the file and automatically
136 * adjust the settings for this buffer only. This must remain at the end
137 * of the file.
138 * ---------------------------------------------------------------------------
139 * Local variables:
140 * c-file-style: "linux"
141 * End:
142 */
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index a0d148ea63d6..10e08a8c17c3 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -15,19 +15,22 @@
15#include "os.h" 15#include "os.h"
16 16
17struct hostaudio_state { 17struct hostaudio_state {
18 int fd; 18 int fd;
19}; 19};
20 20
21struct hostmixer_state { 21struct hostmixer_state {
22 int fd; 22 int fd;
23}; 23};
24 24
25#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" 25#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
26#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" 26#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
27 27
28/* Only changed from linux_main at boot time */ 28/* Changed either at boot time or module load time. At boot, this is
29char *dsp = HOSTAUDIO_DEV_DSP; 29 * single-threaded; at module load, multiple modules would each have
30char *mixer = HOSTAUDIO_DEV_MIXER; 30 * their own copy of these variables.
31 */
32static char *dsp = HOSTAUDIO_DEV_DSP;
33static char *mixer = HOSTAUDIO_DEV_MIXER;
31 34
32#define DSP_HELP \ 35#define DSP_HELP \
33" This is used to specify the host dsp device to the hostaudio driver.\n" \ 36" This is used to specify the host dsp device to the hostaudio driver.\n" \
@@ -69,12 +72,12 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
69static ssize_t hostaudio_read(struct file *file, char __user *buffer, 72static ssize_t hostaudio_read(struct file *file, char __user *buffer,
70 size_t count, loff_t *ppos) 73 size_t count, loff_t *ppos)
71{ 74{
72 struct hostaudio_state *state = file->private_data; 75 struct hostaudio_state *state = file->private_data;
73 void *kbuf; 76 void *kbuf;
74 int err; 77 int err;
75 78
76#ifdef DEBUG 79#ifdef DEBUG
77 printk("hostaudio: read called, count = %d\n", count); 80 printk("hostaudio: read called, count = %d\n", count);
78#endif 81#endif
79 82
80 kbuf = kmalloc(count, GFP_KERNEL); 83 kbuf = kmalloc(count, GFP_KERNEL);
@@ -88,7 +91,7 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer,
88 if(copy_to_user(buffer, kbuf, err)) 91 if(copy_to_user(buffer, kbuf, err))
89 err = -EFAULT; 92 err = -EFAULT;
90 93
91 out: 94out:
92 kfree(kbuf); 95 kfree(kbuf);
93 return(err); 96 return(err);
94} 97}
@@ -96,12 +99,12 @@ static ssize_t hostaudio_read(struct file *file, char __user *buffer,
96static ssize_t hostaudio_write(struct file *file, const char __user *buffer, 99static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
97 size_t count, loff_t *ppos) 100 size_t count, loff_t *ppos)
98{ 101{
99 struct hostaudio_state *state = file->private_data; 102 struct hostaudio_state *state = file->private_data;
100 void *kbuf; 103 void *kbuf;
101 int err; 104 int err;
102 105
103#ifdef DEBUG 106#ifdef DEBUG
104 printk("hostaudio: write called, count = %d\n", count); 107 printk("hostaudio: write called, count = %d\n", count);
105#endif 108#endif
106 109
107 kbuf = kmalloc(count, GFP_KERNEL); 110 kbuf = kmalloc(count, GFP_KERNEL);
@@ -125,24 +128,24 @@ static ssize_t hostaudio_write(struct file *file, const char __user *buffer,
125static unsigned int hostaudio_poll(struct file *file, 128static unsigned int hostaudio_poll(struct file *file,
126 struct poll_table_struct *wait) 129 struct poll_table_struct *wait)
127{ 130{
128 unsigned int mask = 0; 131 unsigned int mask = 0;
129 132
130#ifdef DEBUG 133#ifdef DEBUG
131 printk("hostaudio: poll called (unimplemented)\n"); 134 printk("hostaudio: poll called (unimplemented)\n");
132#endif 135#endif
133 136
134 return(mask); 137 return(mask);
135} 138}
136 139
137static int hostaudio_ioctl(struct inode *inode, struct file *file, 140static int hostaudio_ioctl(struct inode *inode, struct file *file,
138 unsigned int cmd, unsigned long arg) 141 unsigned int cmd, unsigned long arg)
139{ 142{
140 struct hostaudio_state *state = file->private_data; 143 struct hostaudio_state *state = file->private_data;
141 unsigned long data = 0; 144 unsigned long data = 0;
142 int err; 145 int err;
143 146
144#ifdef DEBUG 147#ifdef DEBUG
145 printk("hostaudio: ioctl called, cmd = %u\n", cmd); 148 printk("hostaudio: ioctl called, cmd = %u\n", cmd);
146#endif 149#endif
147 switch(cmd){ 150 switch(cmd){
148 case SNDCTL_DSP_SPEED: 151 case SNDCTL_DSP_SPEED:
@@ -179,42 +182,40 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
179 182
180static int hostaudio_open(struct inode *inode, struct file *file) 183static int hostaudio_open(struct inode *inode, struct file *file)
181{ 184{
182 struct hostaudio_state *state; 185 struct hostaudio_state *state;
183 int r = 0, w = 0; 186 int r = 0, w = 0;
184 int ret; 187 int ret;
185 188
186#ifdef DEBUG 189#ifdef DEBUG
187 printk("hostaudio: open called (host: %s)\n", dsp); 190 printk("hostaudio: open called (host: %s)\n", dsp);
188#endif 191#endif
189 192
190 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); 193 state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
191 if(state == NULL) 194 if(state == NULL)
192 return(-ENOMEM); 195 return(-ENOMEM);
193 196
194 if(file->f_mode & FMODE_READ) r = 1; 197 if(file->f_mode & FMODE_READ) r = 1;
195 if(file->f_mode & FMODE_WRITE) w = 1; 198 if(file->f_mode & FMODE_WRITE) w = 1;
196 199
197 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); 200 ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
198 if(ret < 0){ 201 if(ret < 0){
199 kfree(state); 202 kfree(state);
200 return(ret); 203 return(ret);
201 } 204 }
202
203 state->fd = ret; 205 state->fd = ret;
204 file->private_data = state; 206 file->private_data = state;
205 return(0); 207 return(0);
206} 208}
207 209
208static int hostaudio_release(struct inode *inode, struct file *file) 210static int hostaudio_release(struct inode *inode, struct file *file)
209{ 211{
210 struct hostaudio_state *state = file->private_data; 212 struct hostaudio_state *state = file->private_data;
211 213
212#ifdef DEBUG 214#ifdef DEBUG
213 printk("hostaudio: release called\n"); 215 printk("hostaudio: release called\n");
214#endif 216#endif
215 217 os_close_file(state->fd);
216 os_close_file(state->fd); 218 kfree(state);
217 kfree(state);
218 219
219 return(0); 220 return(0);
220} 221}
@@ -224,10 +225,10 @@ static int hostaudio_release(struct inode *inode, struct file *file)
224static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, 225static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
225 unsigned int cmd, unsigned long arg) 226 unsigned int cmd, unsigned long arg)
226{ 227{
227 struct hostmixer_state *state = file->private_data; 228 struct hostmixer_state *state = file->private_data;
228 229
229#ifdef DEBUG 230#ifdef DEBUG
230 printk("hostmixer: ioctl called\n"); 231 printk("hostmixer: ioctl called\n");
231#endif 232#endif
232 233
233 return(os_ioctl_generic(state->fd, cmd, arg)); 234 return(os_ioctl_generic(state->fd, cmd, arg));
@@ -235,68 +236,67 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
235 236
236static int hostmixer_open_mixdev(struct inode *inode, struct file *file) 237static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
237{ 238{
238 struct hostmixer_state *state; 239 struct hostmixer_state *state;
239 int r = 0, w = 0; 240 int r = 0, w = 0;
240 int ret; 241 int ret;
241 242
242#ifdef DEBUG 243#ifdef DEBUG
243 printk("hostmixer: open called (host: %s)\n", mixer); 244 printk("hostmixer: open called (host: %s)\n", mixer);
244#endif 245#endif
245 246
246 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); 247 state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL);
247 if(state == NULL) return(-ENOMEM); 248 if(state == NULL) return(-ENOMEM);
248 249
249 if(file->f_mode & FMODE_READ) r = 1; 250 if(file->f_mode & FMODE_READ) r = 1;
250 if(file->f_mode & FMODE_WRITE) w = 1; 251 if(file->f_mode & FMODE_WRITE) w = 1;
251 252
252 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); 253 ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
253 254
254 if(ret < 0){ 255 if(ret < 0){
255 printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", 256 printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
256 dsp, -ret); 257 dsp, -ret);
257 kfree(state); 258 kfree(state);
258 return(ret); 259 return(ret);
259 } 260 }
260 261
261 file->private_data = state; 262 file->private_data = state;
262 return(0); 263 return(0);
263} 264}
264 265
265static int hostmixer_release(struct inode *inode, struct file *file) 266static int hostmixer_release(struct inode *inode, struct file *file)
266{ 267{
267 struct hostmixer_state *state = file->private_data; 268 struct hostmixer_state *state = file->private_data;
268 269
269#ifdef DEBUG 270#ifdef DEBUG
270 printk("hostmixer: release called\n"); 271 printk("hostmixer: release called\n");
271#endif 272#endif
272 273
273 os_close_file(state->fd); 274 os_close_file(state->fd);
274 kfree(state); 275 kfree(state);
275 276
276 return(0); 277 return(0);
277} 278}
278 279
279
280/* kernel module operations */ 280/* kernel module operations */
281 281
282static const struct file_operations hostaudio_fops = { 282static const struct file_operations hostaudio_fops = {
283 .owner = THIS_MODULE, 283 .owner = THIS_MODULE,
284 .llseek = no_llseek, 284 .llseek = no_llseek,
285 .read = hostaudio_read, 285 .read = hostaudio_read,
286 .write = hostaudio_write, 286 .write = hostaudio_write,
287 .poll = hostaudio_poll, 287 .poll = hostaudio_poll,
288 .ioctl = hostaudio_ioctl, 288 .ioctl = hostaudio_ioctl,
289 .mmap = NULL, 289 .mmap = NULL,
290 .open = hostaudio_open, 290 .open = hostaudio_open,
291 .release = hostaudio_release, 291 .release = hostaudio_release,
292}; 292};
293 293
294static const struct file_operations hostmixer_fops = { 294static const struct file_operations hostmixer_fops = {
295 .owner = THIS_MODULE, 295 .owner = THIS_MODULE,
296 .llseek = no_llseek, 296 .llseek = no_llseek,
297 .ioctl = hostmixer_ioctl_mixdev, 297 .ioctl = hostmixer_ioctl_mixdev,
298 .open = hostmixer_open_mixdev, 298 .open = hostmixer_open_mixdev,
299 .release = hostmixer_release, 299 .release = hostmixer_release,
300}; 300};
301 301
302struct { 302struct {
@@ -310,42 +310,31 @@ MODULE_LICENSE("GPL");
310 310
311static int __init hostaudio_init_module(void) 311static int __init hostaudio_init_module(void)
312{ 312{
313 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", 313 printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
314 dsp, mixer); 314 dsp, mixer);
315 315
316 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); 316 module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
317 if(module_data.dev_audio < 0){ 317 if(module_data.dev_audio < 0){
318 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); 318 printk(KERN_ERR "hostaudio: couldn't register DSP device!\n");
319 return -ENODEV; 319 return -ENODEV;
320 } 320 }
321 321
322 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); 322 module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1);
323 if(module_data.dev_mixer < 0){ 323 if(module_data.dev_mixer < 0){
324 printk(KERN_ERR "hostmixer: couldn't register mixer " 324 printk(KERN_ERR "hostmixer: couldn't register mixer "
325 "device!\n"); 325 "device!\n");
326 unregister_sound_dsp(module_data.dev_audio); 326 unregister_sound_dsp(module_data.dev_audio);
327 return -ENODEV; 327 return -ENODEV;
328 } 328 }
329 329
330 return 0; 330 return 0;
331} 331}
332 332
333static void __exit hostaudio_cleanup_module (void) 333static void __exit hostaudio_cleanup_module (void)
334{ 334{
335 unregister_sound_mixer(module_data.dev_mixer); 335 unregister_sound_mixer(module_data.dev_mixer);
336 unregister_sound_dsp(module_data.dev_audio); 336 unregister_sound_dsp(module_data.dev_audio);
337} 337}
338 338
339module_init(hostaudio_init_module); 339module_init(hostaudio_init_module);
340module_exit(hostaudio_cleanup_module); 340module_exit(hostaudio_cleanup_module);
341
342/*
343 * Overrides for Emacs so that we follow Linus's tabbing style.
344 * Emacs will notice this stuff at the end of the file and automatically
345 * adjust the settings for this buffer only. This must remain at the end
346 * of the file.
347 * ---------------------------------------------------------------------------
348 * Local variables:
349 * c-file-style: "linux"
350 * End:
351 */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83301e1ef67c..01d4ab6b0ef1 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -191,7 +191,6 @@ void line_flush_buffer(struct tty_struct *tty)
191 /*XXX: copied from line_write, verify if it is correct!*/ 191 /*XXX: copied from line_write, verify if it is correct!*/
192 if(tty->stopped) 192 if(tty->stopped)
193 return; 193 return;
194 //return 0;
195 194
196 spin_lock_irqsave(&line->lock, flags); 195 spin_lock_irqsave(&line->lock, flags);
197 err = flush_buffer(line); 196 err = flush_buffer(line);
@@ -421,42 +420,55 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
421 return err; 420 return err;
422} 421}
423 422
423/* Normally, a driver like this can rely mostly on the tty layer
424 * locking, particularly when it comes to the driver structure.
425 * However, in this case, mconsole requests can come in "from the
426 * side", and race with opens and closes.
427 *
428 * mconsole config requests will want to be sure the device isn't in
429 * use, and get_config, open, and close will want a stable
430 * configuration. The checking and modification of the configuration
431 * is done under a spinlock. Checking whether the device is in use is
432 * line->tty->count > 1, also under the spinlock.
433 *
434 * tty->count serves to decide whether the device should be enabled or
435 * disabled on the host. If it's equal to 1, then we are doing the
436 * first open or last close. Otherwise, open and close just return.
437 */
438
424int line_open(struct line *lines, struct tty_struct *tty) 439int line_open(struct line *lines, struct tty_struct *tty)
425{ 440{
426 struct line *line; 441 struct line *line = &lines[tty->index];
427 int err = -ENODEV; 442 int err = -ENODEV;
428 443
429 line = &lines[tty->index]; 444 spin_lock(&line->count_lock);
430 tty->driver_data = line; 445 if(!line->valid)
446 goto out_unlock;
431 447
432 /* The IRQ which takes this lock is not yet enabled and won't be run 448 err = 0;
433 * before the end, so we don't need to use spin_lock_irq.*/ 449 if(tty->count > 1)
434 spin_lock(&line->lock); 450 goto out_unlock;
451
452 spin_unlock(&line->count_lock);
435 453
436 tty->driver_data = line; 454 tty->driver_data = line;
437 line->tty = tty; 455 line->tty = tty;
438 if(!line->valid)
439 goto out;
440 456
441 if(tty->count == 1){ 457 enable_chan(line);
442 /* Here the device is opened, if necessary, and interrupt 458 INIT_DELAYED_WORK(&line->task, line_timer_cb);
443 * is registered.
444 */
445 enable_chan(line);
446 INIT_DELAYED_WORK(&line->task, line_timer_cb);
447 459
448 if(!line->sigio){ 460 if(!line->sigio){
449 chan_enable_winch(&line->chan_list, tty); 461 chan_enable_winch(&line->chan_list, tty);
450 line->sigio = 1; 462 line->sigio = 1;
451 }
452
453 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
454 &tty->winsize.ws_col);
455 } 463 }
456 464
457 err = 0; 465 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
458out: 466 &tty->winsize.ws_col);
459 spin_unlock(&line->lock); 467
468 return err;
469
470out_unlock:
471 spin_unlock(&line->count_lock);
460 return err; 472 return err;
461} 473}
462 474
@@ -466,25 +478,36 @@ void line_close(struct tty_struct *tty, struct file * filp)
466{ 478{
467 struct line *line = tty->driver_data; 479 struct line *line = tty->driver_data;
468 480
469 /* XXX: I assume this should be called in process context, not with 481 /* If line_open fails (and tty->driver_data is never set),
470 * interrupts disabled! 482 * tty_open will call line_close. So just return in this case.
471 */ 483 */
472 spin_lock_irq(&line->lock); 484 if(line == NULL)
485 return;
473 486
474 /* We ignore the error anyway! */ 487 /* We ignore the error anyway! */
475 flush_buffer(line); 488 flush_buffer(line);
476 489
477 if(tty->count == 1){ 490 spin_lock(&line->count_lock);
478 line->tty = NULL; 491 if(!line->valid)
479 tty->driver_data = NULL; 492 goto out_unlock;
480 493
481 if(line->sigio){ 494 if(tty->count > 1)
482 unregister_winch(tty); 495 goto out_unlock;
483 line->sigio = 0; 496
484 } 497 spin_unlock(&line->count_lock);
498
499 line->tty = NULL;
500 tty->driver_data = NULL;
501
502 if(line->sigio){
503 unregister_winch(tty);
504 line->sigio = 0;
485 } 505 }
486 506
487 spin_unlock_irq(&line->lock); 507 return;
508
509out_unlock:
510 spin_unlock(&line->count_lock);
488} 511}
489 512
490void close_lines(struct line *lines, int nlines) 513void close_lines(struct line *lines, int nlines)
@@ -495,14 +518,44 @@ void close_lines(struct line *lines, int nlines)
495 close_chan(&lines[i].chan_list, 0); 518 close_chan(&lines[i].chan_list, 0);
496} 519}
497 520
521static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
522 char **error_out)
523{
524 struct line *line = &lines[n];
525 int err = -EINVAL;
526
527 spin_lock(&line->count_lock);
528
529 if(line->tty != NULL){
530 *error_out = "Device is already open";
531 goto out;
532 }
533
534 if (line->init_pri <= init_prio){
535 line->init_pri = init_prio;
536 if (!strcmp(init, "none"))
537 line->valid = 0;
538 else {
539 line->init_str = init;
540 line->valid = 1;
541 }
542 }
543 err = 0;
544out:
545 spin_unlock(&line->count_lock);
546 return err;
547}
548
498/* Common setup code for both startup command line and mconsole initialization. 549/* Common setup code for both startup command line and mconsole initialization.
499 * @lines contains the array (of size @num) to modify; 550 * @lines contains the array (of size @num) to modify;
500 * @init is the setup string; 551 * @init is the setup string;
552 * @error_out is an error string in the case of failure;
501 */ 553 */
502 554
503int line_setup(struct line *lines, unsigned int num, char *init) 555int line_setup(struct line *lines, unsigned int num, char *init,
556 char **error_out)
504{ 557{
505 int i, n; 558 int i, n, err;
506 char *end; 559 char *end;
507 560
508 if(*init == '=') { 561 if(*init == '=') {
@@ -513,73 +566,56 @@ int line_setup(struct line *lines, unsigned int num, char *init)
513 else { 566 else {
514 n = simple_strtoul(init, &end, 0); 567 n = simple_strtoul(init, &end, 0);
515 if(*end != '='){ 568 if(*end != '='){
516 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 569 *error_out = "Couldn't parse device number";
517 init); 570 return -EINVAL;
518 return 0;
519 } 571 }
520 init = end; 572 init = end;
521 } 573 }
522 init++; 574 init++;
523 575
524 if (n >= (signed int) num) { 576 if (n >= (signed int) num) {
525 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 577 *error_out = "Device number out of range";
526 n, num - 1); 578 return -EINVAL;
527 return 0;
528 } 579 }
529 else if (n >= 0){ 580 else if (n >= 0){
530 if (lines[n].tty != NULL) { 581 err = setup_one_line(lines, n, init, INIT_ONE, error_out);
531 printk("line_setup - device %d is open\n", n); 582 if(err)
532 return 0; 583 return err;
533 }
534 if (lines[n].init_pri <= INIT_ONE){
535 lines[n].init_pri = INIT_ONE;
536 if (!strcmp(init, "none"))
537 lines[n].valid = 0;
538 else {
539 lines[n].init_str = init;
540 lines[n].valid = 1;
541 }
542 }
543 } 584 }
544 else { 585 else {
545 for(i = 0; i < num; i++){ 586 for(i = 0; i < num; i++){
546 if(lines[i].init_pri <= INIT_ALL){ 587 err = setup_one_line(lines, i, init, INIT_ALL,
547 lines[i].init_pri = INIT_ALL; 588 error_out);
548 if(!strcmp(init, "none")) lines[i].valid = 0; 589 if(err)
549 else { 590 return err;
550 lines[i].init_str = init;
551 lines[i].valid = 1;
552 }
553 }
554 } 591 }
555 } 592 }
556 return n == -1 ? num : n; 593 return n == -1 ? num : n;
557} 594}
558 595
559int line_config(struct line *lines, unsigned int num, char *str, 596int line_config(struct line *lines, unsigned int num, char *str,
560 const struct chan_opts *opts) 597 const struct chan_opts *opts, char **error_out)
561{ 598{
562 struct line *line; 599 struct line *line;
563 char *new; 600 char *new;
564 int n; 601 int n;
565 602
566 if(*str == '='){ 603 if(*str == '='){
567 printk("line_config - can't configure all devices from " 604 *error_out = "Can't configure all devices from mconsole";
568 "mconsole\n"); 605 return -EINVAL;
569 return 1;
570 } 606 }
571 607
572 new = kstrdup(str, GFP_KERNEL); 608 new = kstrdup(str, GFP_KERNEL);
573 if(new == NULL){ 609 if(new == NULL){
574 printk("line_config - kstrdup failed\n"); 610 *error_out = "Failed to allocate memory";
575 return 1; 611 return -ENOMEM;
576 } 612 }
577 n = line_setup(lines, num, new); 613 n = line_setup(lines, num, new, error_out);
578 if(n < 0) 614 if(n < 0)
579 return 1; 615 return n;
580 616
581 line = &lines[n]; 617 line = &lines[n];
582 return parse_chan_pair(line->init_str, line, n, opts); 618 return parse_chan_pair(line->init_str, line, n, opts, error_out);
583} 619}
584 620
585int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 621int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -602,13 +638,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
602 638
603 line = &lines[dev]; 639 line = &lines[dev];
604 640
605 spin_lock(&line->lock); 641 spin_lock(&line->count_lock);
606 if(!line->valid) 642 if(!line->valid)
607 CONFIG_CHUNK(str, size, n, "none", 1); 643 CONFIG_CHUNK(str, size, n, "none", 1);
608 else if(line->tty == NULL) 644 else if(line->tty == NULL)
609 CONFIG_CHUNK(str, size, n, line->init_str, 1); 645 CONFIG_CHUNK(str, size, n, line->init_str, 1);
610 else n = chan_config_string(&line->chan_list, str, size, error_out); 646 else n = chan_config_string(&line->chan_list, str, size, error_out);
611 spin_unlock(&line->lock); 647 spin_unlock(&line->count_lock);
612 648
613 return n; 649 return n;
614} 650}
@@ -628,22 +664,21 @@ int line_id(char **str, int *start_out, int *end_out)
628 return n; 664 return n;
629} 665}
630 666
631int line_remove(struct line *lines, unsigned int num, int n) 667int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
632{ 668{
633 int err; 669 int err;
634 char config[sizeof("conxxxx=none\0")]; 670 char config[sizeof("conxxxx=none\0")];
635 671
636 sprintf(config, "%d=none", n); 672 sprintf(config, "%d=none", n);
637 err = line_setup(lines, num, config); 673 err = line_setup(lines, num, config, error_out);
638 if(err >= 0) 674 if(err >= 0)
639 err = 0; 675 err = 0;
640 return err; 676 return err;
641} 677}
642 678
643struct tty_driver *line_register_devfs(struct lines *set, 679struct tty_driver *register_lines(struct line_driver *line_driver,
644 struct line_driver *line_driver, 680 const struct tty_operations *ops,
645 const struct tty_operations *ops, 681 struct line *lines, int nlines)
646 struct line *lines, int nlines)
647{ 682{
648 int i; 683 int i;
649 struct tty_driver *driver = alloc_tty_driver(nlines); 684 struct tty_driver *driver = alloc_tty_driver(nlines);
@@ -683,6 +718,7 @@ static LIST_HEAD(winch_handlers);
683void lines_init(struct line *lines, int nlines, struct chan_opts *opts) 718void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
684{ 719{
685 struct line *line; 720 struct line *line;
721 char *error;
686 int i; 722 int i;
687 723
688 for(i = 0; i < nlines; i++){ 724 for(i = 0; i < nlines; i++){
@@ -696,8 +732,9 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
696 if(line->init_str == NULL) 732 if(line->init_str == NULL)
697 printk("lines_init - kstrdup returned NULL\n"); 733 printk("lines_init - kstrdup returned NULL\n");
698 734
699 if(parse_chan_pair(line->init_str, line, i, opts)){ 735 if(parse_chan_pair(line->init_str, line, i, opts, &error)){
700 printk("parse_chan_pair failed for device %d\n", i); 736 printk("parse_chan_pair failed for device %d : %s\n",
737 i, error);
701 line->valid = 0; 738 line->valid = 0;
702 } 739 }
703 } 740 }
@@ -737,7 +774,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
737 line = tty->driver_data; 774 line = tty->driver_data;
738 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 775 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
739 &tty->winsize.ws_col); 776 &tty->winsize.ws_col);
740 kill_pg(tty->pgrp, SIGWINCH, 1); 777 kill_pgrp(tty->pgrp, SIGWINCH, 1);
741 } 778 }
742 out: 779 out:
743 if(winch->fd != -1) 780 if(winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 96f0189327af..178b2eff4a8c 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -33,7 +33,6 @@
33#include "irq_user.h" 33#include "irq_user.h"
34#include "init.h" 34#include "init.h"
35#include "os.h" 35#include "os.h"
36#include "umid.h"
37#include "irq_kern.h" 36#include "irq_kern.h"
38#include "choose-mode.h" 37#include "choose-mode.h"
39 38
@@ -337,13 +336,15 @@ void mconsole_stop(struct mc_request *req)
337 mconsole_reply(req, "", 0, 0); 336 mconsole_reply(req, "", 0, 0);
338} 337}
339 338
340/* This list is populated by __initcall routines. */ 339static DEFINE_SPINLOCK(mc_devices_lock);
341
342static LIST_HEAD(mconsole_devices); 340static LIST_HEAD(mconsole_devices);
343 341
344void mconsole_register_dev(struct mc_device *new) 342void mconsole_register_dev(struct mc_device *new)
345{ 343{
344 spin_lock(&mc_devices_lock);
345 BUG_ON(!list_empty(&new->list));
346 list_add(&new->list, &mconsole_devices); 346 list_add(&new->list, &mconsole_devices);
347 spin_unlock(&mc_devices_lock);
347} 348}
348 349
349static struct mc_device *mconsole_find_dev(char *name) 350static struct mc_device *mconsole_find_dev(char *name)
@@ -367,18 +368,21 @@ struct unplugged_pages {
367 void *pages[UNPLUGGED_PER_PAGE]; 368 void *pages[UNPLUGGED_PER_PAGE];
368}; 369};
369 370
371static DECLARE_MUTEX(plug_mem_mutex);
370static unsigned long long unplugged_pages_count = 0; 372static unsigned long long unplugged_pages_count = 0;
371static struct list_head unplugged_pages = LIST_HEAD_INIT(unplugged_pages); 373static LIST_HEAD(unplugged_pages);
372static int unplug_index = UNPLUGGED_PER_PAGE; 374static int unplug_index = UNPLUGGED_PER_PAGE;
373 375
374static int mem_config(char *str) 376static int mem_config(char *str, char **error_out)
375{ 377{
376 unsigned long long diff; 378 unsigned long long diff;
377 int err = -EINVAL, i, add; 379 int err = -EINVAL, i, add;
378 char *ret; 380 char *ret;
379 381
380 if(str[0] != '=') 382 if(str[0] != '='){
383 *error_out = "Expected '=' after 'mem'";
381 goto out; 384 goto out;
385 }
382 386
383 str++; 387 str++;
384 if(str[0] == '-') 388 if(str[0] == '-')
@@ -386,15 +390,21 @@ static int mem_config(char *str)
386 else if(str[0] == '+'){ 390 else if(str[0] == '+'){
387 add = 1; 391 add = 1;
388 } 392 }
389 else goto out; 393 else {
394 *error_out = "Expected increment to start with '-' or '+'";
395 goto out;
396 }
390 397
391 str++; 398 str++;
392 diff = memparse(str, &ret); 399 diff = memparse(str, &ret);
393 if(*ret != '\0') 400 if(*ret != '\0'){
401 *error_out = "Failed to parse memory increment";
394 goto out; 402 goto out;
403 }
395 404
396 diff /= PAGE_SIZE; 405 diff /= PAGE_SIZE;
397 406
407 down(&plug_mem_mutex);
398 for(i = 0; i < diff; i++){ 408 for(i = 0; i < diff; i++){
399 struct unplugged_pages *unplugged; 409 struct unplugged_pages *unplugged;
400 void *addr; 410 void *addr;
@@ -435,11 +445,14 @@ static int mem_config(char *str)
435 unplugged = list_entry(entry, 445 unplugged = list_entry(entry,
436 struct unplugged_pages, 446 struct unplugged_pages,
437 list); 447 list);
438 unplugged->pages[unplug_index++] = addr;
439 err = os_drop_memory(addr, PAGE_SIZE); 448 err = os_drop_memory(addr, PAGE_SIZE);
440 if(err) 449 if(err){
441 printk("Failed to release memory - " 450 printk("Failed to release memory - "
442 "errno = %d\n", err); 451 "errno = %d\n", err);
452 *error_out = "Failed to release memory";
453 goto out_unlock;
454 }
455 unplugged->pages[unplug_index++] = addr;
443 } 456 }
444 457
445 unplugged_pages_count++; 458 unplugged_pages_count++;
@@ -447,6 +460,8 @@ static int mem_config(char *str)
447 } 460 }
448 461
449 err = 0; 462 err = 0;
463out_unlock:
464 up(&plug_mem_mutex);
450out: 465out:
451 return err; 466 return err;
452} 467}
@@ -470,12 +485,14 @@ static int mem_id(char **str, int *start_out, int *end_out)
470 return 0; 485 return 0;
471} 486}
472 487
473static int mem_remove(int n) 488static int mem_remove(int n, char **error_out)
474{ 489{
490 *error_out = "Memory doesn't support the remove operation";
475 return -EBUSY; 491 return -EBUSY;
476} 492}
477 493
478static struct mc_device mem_mc = { 494static struct mc_device mem_mc = {
495 .list = LIST_HEAD_INIT(mem_mc.list),
479 .name = "mem", 496 .name = "mem",
480 .config = mem_config, 497 .config = mem_config,
481 .get_config = mem_get_config, 498 .get_config = mem_get_config,
@@ -542,7 +559,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
542void mconsole_config(struct mc_request *req) 559void mconsole_config(struct mc_request *req)
543{ 560{
544 struct mc_device *dev; 561 struct mc_device *dev;
545 char *ptr = req->request.data, *name; 562 char *ptr = req->request.data, *name, *error_string = "";
546 int err; 563 int err;
547 564
548 ptr += strlen("config"); 565 ptr += strlen("config");
@@ -559,8 +576,8 @@ void mconsole_config(struct mc_request *req)
559 ptr++; 576 ptr++;
560 577
561 if(*ptr == '='){ 578 if(*ptr == '='){
562 err = (*dev->config)(name); 579 err = (*dev->config)(name, &error_string);
563 mconsole_reply(req, "", err, 0); 580 mconsole_reply(req, error_string, err, 0);
564 } 581 }
565 else mconsole_get_config(dev->get_config, req, name); 582 else mconsole_get_config(dev->get_config, req, name);
566} 583}
@@ -595,13 +612,16 @@ void mconsole_remove(struct mc_request *req)
595 goto out; 612 goto out;
596 } 613 }
597 614
598 err = (*dev->remove)(n); 615 err_msg = NULL;
616 err = (*dev->remove)(n, &err_msg);
599 switch(err){ 617 switch(err){
600 case -ENODEV: 618 case -ENODEV:
601 err_msg = "Device doesn't exist"; 619 if(err_msg == NULL)
620 err_msg = "Device doesn't exist";
602 break; 621 break;
603 case -EBUSY: 622 case -EBUSY:
604 err_msg = "Device is currently open"; 623 if(err_msg == NULL)
624 err_msg = "Device is currently open";
605 break; 625 break;
606 default: 626 default:
607 break; 627 break;
@@ -615,7 +635,7 @@ struct mconsole_output {
615 struct mc_request *req; 635 struct mc_request *req;
616}; 636};
617 637
618static DEFINE_SPINLOCK(console_lock); 638static DEFINE_SPINLOCK(client_lock);
619static LIST_HEAD(clients); 639static LIST_HEAD(clients);
620static char console_buf[MCONSOLE_MAX_DATA]; 640static char console_buf[MCONSOLE_MAX_DATA];
621static int console_index = 0; 641static int console_index = 0;
@@ -670,16 +690,18 @@ static void with_console(struct mc_request *req, void (*proc)(void *),
670 unsigned long flags; 690 unsigned long flags;
671 691
672 entry.req = req; 692 entry.req = req;
693 spin_lock_irqsave(&client_lock, flags);
673 list_add(&entry.list, &clients); 694 list_add(&entry.list, &clients);
674 spin_lock_irqsave(&console_lock, flags); 695 spin_unlock_irqrestore(&client_lock, flags);
675 696
676 (*proc)(arg); 697 (*proc)(arg);
677 698
678 mconsole_reply_len(req, console_buf, console_index, 0, 0); 699 mconsole_reply_len(req, console_buf, console_index, 0, 0);
679 console_index = 0; 700 console_index = 0;
680 701
681 spin_unlock_irqrestore(&console_lock, flags); 702 spin_lock_irqsave(&client_lock, flags);
682 list_del(&entry.list); 703 list_del(&entry.list);
704 spin_unlock_irqrestore(&client_lock, flags);
683} 705}
684 706
685#ifdef CONFIG_MAGIC_SYSRQ 707#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 75aef6f7ef6e..f02634fbf32a 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -16,7 +16,7 @@
16#include "user.h" 16#include "user.h"
17#include "sysdep/ptrace.h" 17#include "sysdep/ptrace.h"
18#include "mconsole.h" 18#include "mconsole.h"
19#include "umid.h" 19#include "os.h"
20#include "user_util.h" 20#include "user_util.h"
21 21
22static struct mconsole_command commands[] = { 22static struct mconsole_command commands[] = {
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index afe3d427ddfa..04e31f86c10a 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net). 3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here. 4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL. 5 * Licensed under the GPL.
@@ -91,8 +91,8 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
91 spin_lock(&lp->lock); 91 spin_lock(&lp->lock);
92 while((err = uml_net_rx(dev)) > 0) ; 92 while((err = uml_net_rx(dev)) > 0) ;
93 if(err < 0) { 93 if(err < 0) {
94 printk(KERN_ERR 94 printk(KERN_ERR
95 "Device '%s' read returned %d, shutting it down\n", 95 "Device '%s' read returned %d, shutting it down\n",
96 dev->name, err); 96 dev->name, err);
97 /* dev_close can't be called in interrupt context, and takes 97 /* dev_close can't be called in interrupt context, and takes
98 * again lp->lock. 98 * again lp->lock.
@@ -108,7 +108,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id)
108 108
109out: 109out:
110 spin_unlock(&lp->lock); 110 spin_unlock(&lp->lock);
111 return(IRQ_HANDLED); 111 return IRQ_HANDLED;
112} 112}
113 113
114static int uml_net_open(struct net_device *dev) 114static int uml_net_open(struct net_device *dev)
@@ -159,7 +159,7 @@ out:
159static int uml_net_close(struct net_device *dev) 159static int uml_net_close(struct net_device *dev)
160{ 160{
161 struct uml_net_private *lp = dev->priv; 161 struct uml_net_private *lp = dev->priv;
162 162
163 netif_stop_queue(dev); 163 netif_stop_queue(dev);
164 164
165 free_irq(dev->irq, dev); 165 free_irq(dev->irq, dev);
@@ -194,7 +194,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
194 194
195 /* this is normally done in the interrupt when tx finishes */ 195 /* this is normally done in the interrupt when tx finishes */
196 netif_wake_queue(dev); 196 netif_wake_queue(dev);
197 } 197 }
198 else if(len == 0){ 198 else if(len == 0){
199 netif_start_queue(dev); 199 netif_start_queue(dev);
200 lp->stats.tx_dropped++; 200 lp->stats.tx_dropped++;
@@ -239,7 +239,7 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
239 set_ether_mac(dev, hwaddr->sa_data); 239 set_ether_mac(dev, hwaddr->sa_data);
240 spin_unlock_irq(&lp->lock); 240 spin_unlock_irq(&lp->lock);
241 241
242 return(0); 242 return 0;
243} 243}
244 244
245static int uml_net_change_mtu(struct net_device *dev, int new_mtu) 245static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
@@ -333,7 +333,7 @@ static int eth_configure(int n, void *init, char *mac,
333 struct uml_net_private *lp; 333 struct uml_net_private *lp;
334 int save, err, size; 334 int save, err, size;
335 335
336 size = transport->private_size + sizeof(struct uml_net_private) + 336 size = transport->private_size + sizeof(struct uml_net_private) +
337 sizeof(((struct uml_net_private *) 0)->user); 337 sizeof(((struct uml_net_private *) 0)->user);
338 338
339 device = kzalloc(sizeof(*device), GFP_KERNEL); 339 device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -438,7 +438,7 @@ static int eth_configure(int n, void *init, char *mac,
438 lp->tl.function = uml_net_user_timer_expire; 438 lp->tl.function = uml_net_user_timer_expire;
439 memcpy(lp->mac, device->mac, sizeof(lp->mac)); 439 memcpy(lp->mac, device->mac, sizeof(lp->mac));
440 440
441 if (transport->user->init) 441 if (transport->user->init)
442 (*transport->user->init)(&lp->user, dev); 442 (*transport->user->init)(&lp->user, dev);
443 443
444 set_ether_mac(dev, device->mac); 444 set_ether_mac(dev, device->mac);
@@ -460,38 +460,36 @@ static struct uml_net *find_device(int n)
460 device = NULL; 460 device = NULL;
461 out: 461 out:
462 spin_unlock(&devices_lock); 462 spin_unlock(&devices_lock);
463 return(device); 463 return device;
464} 464}
465 465
466static int eth_parse(char *str, int *index_out, char **str_out) 466static int eth_parse(char *str, int *index_out, char **str_out,
467 char **error_out)
467{ 468{
468 char *end; 469 char *end;
469 int n; 470 int n, err = -EINVAL;;
470 471
471 n = simple_strtoul(str, &end, 0); 472 n = simple_strtoul(str, &end, 0);
472 if(end == str){ 473 if(end == str){
473 printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); 474 *error_out = "Bad device number";
474 return(1); 475 return err;
475 }
476 if(n < 0){
477 printk(KERN_ERR "eth_setup: device %d is negative\n", n);
478 return(1);
479 } 476 }
477
480 str = end; 478 str = end;
481 if(*str != '='){ 479 if(*str != '='){
482 printk(KERN_ERR 480 *error_out = "Expected '=' after device number";
483 "eth_setup: expected '=' after device number\n"); 481 return err;
484 return(1);
485 } 482 }
483
486 str++; 484 str++;
487 if(find_device(n)){ 485 if(find_device(n)){
488 printk(KERN_ERR "eth_setup: Device %d already configured\n", 486 *error_out = "Device already configured";
489 n); 487 return err;
490 return(1);
491 } 488 }
492 if(index_out) *index_out = n; 489
490 *index_out = n;
493 *str_out = str; 491 *str_out = str;
494 return(0); 492 return 0;
495} 493}
496 494
497struct eth_init { 495struct eth_init {
@@ -500,13 +498,11 @@ struct eth_init {
500 int index; 498 int index;
501}; 499};
502 500
503/* Filled in at boot time. Will need locking if the transports become 501static DEFINE_SPINLOCK(transports_lock);
504 * modular. 502static LIST_HEAD(transports);
505 */
506struct list_head transports = LIST_HEAD_INIT(transports);
507 503
508/* Filled in during early boot */ 504/* Filled in during early boot */
509struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); 505static LIST_HEAD(eth_cmd_line);
510 506
511static int check_transport(struct transport *transport, char *eth, int n, 507static int check_transport(struct transport *transport, char *eth, int n,
512 void **init_out, char **mac_out) 508 void **init_out, char **mac_out)
@@ -515,23 +511,23 @@ static int check_transport(struct transport *transport, char *eth, int n,
515 511
516 len = strlen(transport->name); 512 len = strlen(transport->name);
517 if(strncmp(eth, transport->name, len)) 513 if(strncmp(eth, transport->name, len))
518 return(0); 514 return 0;
519 515
520 eth += len; 516 eth += len;
521 if(*eth == ',') 517 if(*eth == ',')
522 eth++; 518 eth++;
523 else if(*eth != '\0') 519 else if(*eth != '\0')
524 return(0); 520 return 0;
525 521
526 *init_out = kmalloc(transport->setup_size, GFP_KERNEL); 522 *init_out = kmalloc(transport->setup_size, GFP_KERNEL);
527 if(*init_out == NULL) 523 if(*init_out == NULL)
528 return(1); 524 return 1;
529 525
530 if(!transport->setup(eth, mac_out, *init_out)){ 526 if(!transport->setup(eth, mac_out, *init_out)){
531 kfree(*init_out); 527 kfree(*init_out);
532 *init_out = NULL; 528 *init_out = NULL;
533 } 529 }
534 return(1); 530 return 1;
535} 531}
536 532
537void register_transport(struct transport *new) 533void register_transport(struct transport *new)
@@ -542,7 +538,10 @@ void register_transport(struct transport *new)
542 char *mac = NULL; 538 char *mac = NULL;
543 int match; 539 int match;
544 540
541 spin_lock(&transports_lock);
542 BUG_ON(!list_empty(&new->list));
545 list_add(&new->list, &transports); 543 list_add(&new->list, &transports);
544 spin_unlock(&transports_lock);
546 545
547 list_for_each_safe(ele, next, &eth_cmd_line){ 546 list_for_each_safe(ele, next, &eth_cmd_line){
548 eth = list_entry(ele, struct eth_init, list); 547 eth = list_entry(ele, struct eth_init, list);
@@ -564,7 +563,9 @@ static int eth_setup_common(char *str, int index)
564 struct transport *transport; 563 struct transport *transport;
565 void *init; 564 void *init;
566 char *mac = NULL; 565 char *mac = NULL;
566 int found = 0;
567 567
568 spin_lock(&transports_lock);
568 list_for_each(ele, &transports){ 569 list_for_each(ele, &transports){
569 transport = list_entry(ele, struct transport, list); 570 transport = list_entry(ele, struct transport, list);
570 if(!check_transport(transport, str, index, &init, &mac)) 571 if(!check_transport(transport, str, index, &init, &mac))
@@ -573,19 +574,26 @@ static int eth_setup_common(char *str, int index)
573 eth_configure(index, init, mac, transport); 574 eth_configure(index, init, mac, transport);
574 kfree(init); 575 kfree(init);
575 } 576 }
576 return(1); 577 found = 1;
578 break;
577 } 579 }
578 return(0); 580
581 spin_unlock(&transports_lock);
582 return found;
579} 583}
580 584
581static int eth_setup(char *str) 585static int eth_setup(char *str)
582{ 586{
583 struct eth_init *new; 587 struct eth_init *new;
588 char *error;
584 int n, err; 589 int n, err;
585 590
586 err = eth_parse(str, &n, &str); 591 err = eth_parse(str, &n, &str, &error);
587 if(err) 592 if(err){
593 printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n",
594 str, error);
588 return 1; 595 return 1;
596 }
589 597
590 new = alloc_bootmem(sizeof(*new)); 598 new = alloc_bootmem(sizeof(*new));
591 if (new == NULL){ 599 if (new == NULL){
@@ -607,38 +615,24 @@ __uml_help(eth_setup,
607" Configure a network device.\n\n" 615" Configure a network device.\n\n"
608); 616);
609 617
610#if 0 618static int net_config(char *str, char **error_out)
611static int eth_init(void)
612{
613 struct list_head *ele, *next;
614 struct eth_init *eth;
615
616 list_for_each_safe(ele, next, &eth_cmd_line){
617 eth = list_entry(ele, struct eth_init, list);
618
619 if(eth_setup_common(eth->init, eth->index))
620 list_del(&eth->list);
621 }
622
623 return(1);
624}
625__initcall(eth_init);
626#endif
627
628static int net_config(char *str)
629{ 619{
630 int n, err; 620 int n, err;
631 621
632 err = eth_parse(str, &n, &str); 622 err = eth_parse(str, &n, &str, error_out);
633 if(err) return(err); 623 if(err)
624 return err;
634 625
626 /* This string is broken up and the pieces used by the underlying
627 * driver. So, it is freed only if eth_setup_common fails.
628 */
635 str = kstrdup(str, GFP_KERNEL); 629 str = kstrdup(str, GFP_KERNEL);
636 if(str == NULL){ 630 if(str == NULL){
637 printk(KERN_ERR "net_config failed to strdup string\n"); 631 *error_out = "net_config failed to strdup string";
638 return(-1); 632 return -ENOMEM;
639 } 633 }
640 err = !eth_setup_common(str, n); 634 err = !eth_setup_common(str, n);
641 if(err) 635 if(err)
642 kfree(str); 636 kfree(str);
643 return(err); 637 return(err);
644} 638}
@@ -658,7 +652,7 @@ static int net_id(char **str, int *start_out, int *end_out)
658 return n; 652 return n;
659} 653}
660 654
661static int net_remove(int n) 655static int net_remove(int n, char **error_out)
662{ 656{
663 struct uml_net *device; 657 struct uml_net *device;
664 struct net_device *dev; 658 struct net_device *dev;
@@ -671,7 +665,7 @@ static int net_remove(int n)
671 dev = device->dev; 665 dev = device->dev;
672 lp = dev->priv; 666 lp = dev->priv;
673 if(lp->fd > 0) 667 if(lp->fd > 0)
674 return -EBUSY; 668 return -EBUSY;
675 if(lp->remove != NULL) (*lp->remove)(&lp->user); 669 if(lp->remove != NULL) (*lp->remove)(&lp->user);
676 unregister_netdev(dev); 670 unregister_netdev(dev);
677 platform_device_unregister(&device->pdev); 671 platform_device_unregister(&device->pdev);
@@ -683,10 +677,11 @@ static int net_remove(int n)
683} 677}
684 678
685static struct mc_device net_mc = { 679static struct mc_device net_mc = {
680 .list = LIST_HEAD_INIT(net_mc.list),
686 .name = "eth", 681 .name = "eth",
687 .config = net_config, 682 .config = net_config,
688 .get_config = NULL, 683 .get_config = NULL,
689 .id = net_id, 684 .id = net_id,
690 .remove = net_remove, 685 .remove = net_remove,
691}; 686};
692 687
@@ -699,7 +694,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
699 void (*proc)(unsigned char *, unsigned char *, void *); 694 void (*proc)(unsigned char *, unsigned char *, void *);
700 unsigned char addr_buf[4], netmask_buf[4]; 695 unsigned char addr_buf[4], netmask_buf[4];
701 696
702 if(dev->open != uml_net_open) return(NOTIFY_DONE); 697 if(dev->open != uml_net_open)
698 return NOTIFY_DONE;
703 699
704 lp = dev->priv; 700 lp = dev->priv;
705 701
@@ -717,9 +713,10 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
717 memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf)); 713 memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
718 (*proc)(addr_buf, netmask_buf, &lp->user); 714 (*proc)(addr_buf, netmask_buf, &lp->user);
719 } 715 }
720 return(NOTIFY_DONE); 716 return NOTIFY_DONE;
721} 717}
722 718
719/* uml_net_init shouldn't be called twice on two CPUs at the same time */
723struct notifier_block uml_inetaddr_notifier = { 720struct notifier_block uml_inetaddr_notifier = {
724 .notifier_call = uml_inetaddr_event, 721 .notifier_call = uml_inetaddr_event,
725}; 722};
@@ -727,7 +724,7 @@ struct notifier_block uml_inetaddr_notifier = {
727static int uml_net_init(void) 724static int uml_net_init(void)
728{ 725{
729 struct list_head *ele; 726 struct list_head *ele;
730 struct uml_net_private *lp; 727 struct uml_net_private *lp;
731 struct in_device *ip; 728 struct in_device *ip;
732 struct in_ifaddr *in; 729 struct in_ifaddr *in;
733 730
@@ -738,18 +735,21 @@ static int uml_net_init(void)
738 * didn't get a chance to run for them. This fakes it so that 735 * didn't get a chance to run for them. This fakes it so that
739 * addresses which have already been set up get handled properly. 736 * addresses which have already been set up get handled properly.
740 */ 737 */
738 spin_lock(&opened_lock);
741 list_for_each(ele, &opened){ 739 list_for_each(ele, &opened){
742 lp = list_entry(ele, struct uml_net_private, list); 740 lp = list_entry(ele, struct uml_net_private, list);
743 ip = lp->dev->ip_ptr; 741 ip = lp->dev->ip_ptr;
744 if(ip == NULL) continue; 742 if(ip == NULL)
743 continue;
745 in = ip->ifa_list; 744 in = ip->ifa_list;
746 while(in != NULL){ 745 while(in != NULL){
747 uml_inetaddr_event(NULL, NETDEV_UP, in); 746 uml_inetaddr_event(NULL, NETDEV_UP, in);
748 in = in->ifa_next; 747 in = in->ifa_next;
749 } 748 }
750 } 749 }
750 spin_unlock(&opened_lock);
751 751
752 return(0); 752 return 0;
753} 753}
754 754
755__initcall(uml_net_init); 755__initcall(uml_net_init);
@@ -759,13 +759,16 @@ static void close_devices(void)
759 struct list_head *ele; 759 struct list_head *ele;
760 struct uml_net_private *lp; 760 struct uml_net_private *lp;
761 761
762 spin_lock(&opened_lock);
762 list_for_each(ele, &opened){ 763 list_for_each(ele, &opened){
763 lp = list_entry(ele, struct uml_net_private, list); 764 lp = list_entry(ele, struct uml_net_private, list);
764 free_irq(lp->dev->irq, lp->dev); 765 free_irq(lp->dev->irq, lp->dev);
765 if((lp->close != NULL) && (lp->fd >= 0)) 766 if((lp->close != NULL) && (lp->fd >= 0))
766 (*lp->close)(lp->fd, &lp->user); 767 (*lp->close)(lp->fd, &lp->user);
767 if(lp->remove != NULL) (*lp->remove)(&lp->user); 768 if(lp->remove != NULL)
769 (*lp->remove)(&lp->user);
768 } 770 }
771 spin_unlock(&opened_lock);
769} 772}
770 773
771__uml_exitcall(close_devices); 774__uml_exitcall(close_devices);
@@ -783,8 +786,8 @@ struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
783 return(skb); 786 return(skb);
784} 787}
785 788
786void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 789void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
787 void *), 790 void *),
788 void *arg) 791 void *arg)
789{ 792{
790 struct net_device *dev = d; 793 struct net_device *dev = d;
@@ -809,11 +812,11 @@ int dev_netmask(void *d, void *m)
809 struct in_ifaddr *in; 812 struct in_ifaddr *in;
810 __be32 *mask_out = m; 813 __be32 *mask_out = m;
811 814
812 if(ip == NULL) 815 if(ip == NULL)
813 return(1); 816 return(1);
814 817
815 in = ip->ifa_list; 818 in = ip->ifa_list;
816 if(in == NULL) 819 if(in == NULL)
817 return(1); 820 return(1);
818 821
819 *mask_out = in->ifa_mask; 822 *mask_out = in->ifa_mask;
@@ -827,7 +830,7 @@ void *get_output_buffer(int *len_out)
827 ret = (void *) __get_free_pages(GFP_KERNEL, 0); 830 ret = (void *) __get_free_pages(GFP_KERNEL, 0);
828 if(ret) *len_out = PAGE_SIZE; 831 if(ret) *len_out = PAGE_SIZE;
829 else *len_out = 0; 832 else *len_out = 0;
830 return(ret); 833 return ret;
831} 834}
832 835
833void free_output_buffer(void *buffer) 836void free_output_buffer(void *buffer)
@@ -835,7 +838,7 @@ void free_output_buffer(void *buffer)
835 free_pages((unsigned long) buffer, 0); 838 free_pages((unsigned long) buffer, 0);
836} 839}
837 840
838int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, 841int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
839 char **gate_addr) 842 char **gate_addr)
840{ 843{
841 char *remain; 844 char *remain;
@@ -854,14 +857,3 @@ unsigned short eth_protocol(struct sk_buff *skb)
854{ 857{
855 return(eth_type_trans(skb, skb->dev)); 858 return(eth_type_trans(skb, skb->dev));
856} 859}
857
858/*
859 * Overrides for Emacs so that we follow Linus's tabbing style.
860 * Emacs will notice this stuff at the end of the file and automatically
861 * adjust the settings for this buffer only. This must remain at the end
862 * of the file.
863 * ---------------------------------------------------------------------------
864 * Local variables:
865 * c-file-style: "linux"
866 * End:
867 */
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 6dfe632f1c14..1c8efd95c421 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -55,9 +55,9 @@ static irqreturn_t pipe_interrupt(int irq, void *data)
55 fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); 55 fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
56 if(fd < 0){ 56 if(fd < 0){
57 if(fd == -EAGAIN) 57 if(fd == -EAGAIN)
58 return(IRQ_NONE); 58 return IRQ_NONE;
59 59
60 printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 60 printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
61 -fd); 61 -fd);
62 os_close_file(conn->fd); 62 os_close_file(conn->fd);
63 } 63 }
@@ -68,7 +68,7 @@ static irqreturn_t pipe_interrupt(int irq, void *data)
68 list_add(&conn->list, &conn->port->connections); 68 list_add(&conn->list, &conn->port->connections);
69 69
70 complete(&conn->port->done); 70 complete(&conn->port->done);
71 return(IRQ_HANDLED); 71 return IRQ_HANDLED;
72} 72}
73 73
74#define NO_WAITER_MSG \ 74#define NO_WAITER_MSG \
@@ -97,14 +97,14 @@ static int port_accept(struct port_list *port)
97 "connection\n"); 97 "connection\n");
98 goto out_close; 98 goto out_close;
99 } 99 }
100 *conn = ((struct connection) 100 *conn = ((struct connection)
101 { .list = LIST_HEAD_INIT(conn->list), 101 { .list = LIST_HEAD_INIT(conn->list),
102 .fd = fd, 102 .fd = fd,
103 .socket = { socket[0], socket[1] }, 103 .socket = { socket[0], socket[1] },
104 .telnetd_pid = pid, 104 .telnetd_pid = pid,
105 .port = port }); 105 .port = port });
106 106
107 if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, 107 if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
108 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, 108 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
109 "telnetd", conn)){ 109 "telnetd", conn)){
110 printk(KERN_ERR "port_accept : failed to get IRQ for " 110 printk(KERN_ERR "port_accept : failed to get IRQ for "
@@ -117,20 +117,20 @@ static int port_accept(struct port_list *port)
117 printk("No one waiting for port\n"); 117 printk("No one waiting for port\n");
118 } 118 }
119 list_add(&conn->list, &port->pending); 119 list_add(&conn->list, &port->pending);
120 return(1); 120 return 1;
121 121
122 out_free: 122 out_free:
123 kfree(conn); 123 kfree(conn);
124 out_close: 124 out_close:
125 os_close_file(fd); 125 os_close_file(fd);
126 if(pid != -1) 126 if(pid != -1)
127 os_kill_process(pid, 1); 127 os_kill_process(pid, 1);
128 out: 128 out:
129 return(ret); 129 return ret;
130} 130}
131 131
132DECLARE_MUTEX(ports_sem); 132static DECLARE_MUTEX(ports_sem);
133struct list_head ports = LIST_HEAD_INIT(ports); 133static LIST_HEAD(ports);
134 134
135void port_work_proc(struct work_struct *unused) 135void port_work_proc(struct work_struct *unused)
136{ 136{
@@ -158,8 +158,8 @@ static irqreturn_t port_interrupt(int irq, void *data)
158 158
159 port->has_connection = 1; 159 port->has_connection = 1;
160 schedule_work(&port_work); 160 schedule_work(&port_work);
161 return(IRQ_HANDLED); 161 return IRQ_HANDLED;
162} 162}
163 163
164void *port_data(int port_num) 164void *port_data(int port_num)
165{ 165{
@@ -185,14 +185,14 @@ void *port_data(int port_num)
185 port_num, -fd); 185 port_num, -fd);
186 goto out_free; 186 goto out_free;
187 } 187 }
188 if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, 188 if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
189 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port", 189 IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
190 port)){ 190 "port", port)){
191 printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); 191 printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
192 goto out_close; 192 goto out_close;
193 } 193 }
194 194
195 *port = ((struct port_list) 195 *port = ((struct port_list)
196 { .list = LIST_HEAD_INIT(port->list), 196 { .list = LIST_HEAD_INIT(port->list),
197 .wait_count = ATOMIC_INIT(0), 197 .wait_count = ATOMIC_INIT(0),
198 .has_connection = 0, 198 .has_connection = 0,
@@ -222,7 +222,7 @@ void *port_data(int port_num)
222 os_close_file(fd); 222 os_close_file(fd);
223 out: 223 out:
224 up(&ports_sem); 224 up(&ports_sem);
225 return(dev); 225 return dev;
226} 226}
227 227
228int port_wait(void *data) 228int port_wait(void *data)
@@ -232,15 +232,15 @@ int port_wait(void *data)
232 struct port_list *port = dev->port; 232 struct port_list *port = dev->port;
233 int fd; 233 int fd;
234 234
235 atomic_inc(&port->wait_count); 235 atomic_inc(&port->wait_count);
236 while(1){ 236 while(1){
237 fd = -ERESTARTSYS; 237 fd = -ERESTARTSYS;
238 if(wait_for_completion_interruptible(&port->done)) 238 if(wait_for_completion_interruptible(&port->done))
239 goto out; 239 goto out;
240 240
241 spin_lock(&port->lock); 241 spin_lock(&port->lock);
242 242
243 conn = list_entry(port->connections.next, struct connection, 243 conn = list_entry(port->connections.next, struct connection,
244 list); 244 list);
245 list_del(&conn->list); 245 list_del(&conn->list);
246 spin_unlock(&port->lock); 246 spin_unlock(&port->lock);
@@ -248,12 +248,12 @@ int port_wait(void *data)
248 os_shutdown_socket(conn->socket[0], 1, 1); 248 os_shutdown_socket(conn->socket[0], 1, 1);
249 os_close_file(conn->socket[0]); 249 os_close_file(conn->socket[0]);
250 os_shutdown_socket(conn->socket[1], 1, 1); 250 os_shutdown_socket(conn->socket[1], 1, 1);
251 os_close_file(conn->socket[1]); 251 os_close_file(conn->socket[1]);
252 252
253 /* This is done here because freeing an IRQ can't be done 253 /* This is done here because freeing an IRQ can't be done
254 * within the IRQ handler. So, pipe_interrupt always ups 254 * within the IRQ handler. So, pipe_interrupt always ups
255 * the semaphore regardless of whether it got a successful 255 * the semaphore regardless of whether it got a successful
256 * connection. Then we loop here throwing out failed 256 * connection. Then we loop here throwing out failed
257 * connections until a good one is found. 257 * connections until a good one is found.
258 */ 258 */
259 free_irq(TELNETD_IRQ, conn); 259 free_irq(TELNETD_IRQ, conn);
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index bc6afaf74c1a..80508023054f 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -38,18 +38,18 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
38 if(*str != ':'){ 38 if(*str != ':'){
39 printk("port_init : channel type 'port' must specify a " 39 printk("port_init : channel type 'port' must specify a "
40 "port number\n"); 40 "port number\n");
41 return(NULL); 41 return NULL;
42 } 42 }
43 str++; 43 str++;
44 port = strtoul(str, &end, 0); 44 port = strtoul(str, &end, 0);
45 if((*end != '\0') || (end == str)){ 45 if((*end != '\0') || (end == str)){
46 printk("port_init : couldn't parse port '%s'\n", str); 46 printk("port_init : couldn't parse port '%s'\n", str);
47 return(NULL); 47 return NULL;
48 } 48 }
49 49
50 kern_data = port_data(port); 50 kern_data = port_data(port);
51 if(kern_data == NULL) 51 if(kern_data == NULL)
52 return(NULL); 52 return NULL;
53 53
54 data = um_kmalloc(sizeof(*data)); 54 data = um_kmalloc(sizeof(*data));
55 if(data == NULL) 55 if(data == NULL)
@@ -59,10 +59,10 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
59 .kernel_data = kern_data }); 59 .kernel_data = kern_data });
60 sprintf(data->dev, "%d", port); 60 sprintf(data->dev, "%d", port);
61 61
62 return(data); 62 return data;
63 err: 63 err:
64 port_kern_free(kern_data); 64 port_kern_free(kern_data);
65 return(NULL); 65 return NULL;
66} 66}
67 67
68static void port_free(void *d) 68static void port_free(void *d)
@@ -83,14 +83,14 @@ static int port_open(int input, int output, int primary, void *d,
83 if((fd >= 0) && data->raw){ 83 if((fd >= 0) && data->raw){
84 CATCH_EINTR(err = tcgetattr(fd, &data->tt)); 84 CATCH_EINTR(err = tcgetattr(fd, &data->tt));
85 if(err) 85 if(err)
86 return(err); 86 return err;
87 87
88 err = raw(fd); 88 err = raw(fd);
89 if(err) 89 if(err)
90 return(err); 90 return err;
91 } 91 }
92 *dev_out = data->dev; 92 *dev_out = data->dev;
93 return(fd); 93 return fd;
94} 94}
95 95
96static void port_close(int fd, void *d) 96static void port_close(int fd, void *d)
@@ -120,8 +120,8 @@ int port_listen_fd(int port)
120 int fd, err, arg; 120 int fd, err, arg;
121 121
122 fd = socket(PF_INET, SOCK_STREAM, 0); 122 fd = socket(PF_INET, SOCK_STREAM, 0);
123 if(fd == -1) 123 if(fd == -1)
124 return(-errno); 124 return -errno;
125 125
126 arg = 1; 126 arg = 1;
127 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ 127 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){
@@ -136,7 +136,7 @@ int port_listen_fd(int port)
136 err = -errno; 136 err = -errno;
137 goto out; 137 goto out;
138 } 138 }
139 139
140 if(listen(fd, 1) < 0){ 140 if(listen(fd, 1) < 0){
141 err = -errno; 141 err = -errno;
142 goto out; 142 goto out;
@@ -146,10 +146,10 @@ int port_listen_fd(int port)
146 if(err < 0) 146 if(err < 0)
147 goto out; 147 goto out;
148 148
149 return(fd); 149 return fd;
150 out: 150 out:
151 os_close_file(fd); 151 os_close_file(fd);
152 return(err); 152 return err;
153} 153}
154 154
155struct port_pre_exec_data { 155struct port_pre_exec_data {
@@ -173,13 +173,13 @@ void port_pre_exec(void *arg)
173int port_connection(int fd, int *socket, int *pid_out) 173int port_connection(int fd, int *socket, int *pid_out)
174{ 174{
175 int new, err; 175 int new, err;
176 char *argv[] = { "/usr/sbin/in.telnetd", "-L", 176 char *argv[] = { "/usr/sbin/in.telnetd", "-L",
177 "/usr/lib/uml/port-helper", NULL }; 177 "/usr/lib/uml/port-helper", NULL };
178 struct port_pre_exec_data data; 178 struct port_pre_exec_data data;
179 179
180 new = os_accept_connection(fd); 180 new = os_accept_connection(fd);
181 if(new < 0) 181 if(new < 0)
182 return(new); 182 return new;
183 183
184 err = os_pipe(socket, 0, 0); 184 err = os_pipe(socket, 0, 0);
185 if(err < 0) 185 if(err < 0)
@@ -190,29 +190,18 @@ int port_connection(int fd, int *socket, int *pid_out)
190 .pipe_fd = socket[1] }); 190 .pipe_fd = socket[1] });
191 191
192 err = run_helper(port_pre_exec, &data, argv, NULL); 192 err = run_helper(port_pre_exec, &data, argv, NULL);
193 if(err < 0) 193 if(err < 0)
194 goto out_shutdown; 194 goto out_shutdown;
195 195
196 *pid_out = err; 196 *pid_out = err;
197 return(new); 197 return new;
198 198
199 out_shutdown: 199 out_shutdown:
200 os_shutdown_socket(socket[0], 1, 1); 200 os_shutdown_socket(socket[0], 1, 1);
201 os_close_file(socket[0]); 201 os_close_file(socket[0]);
202 os_shutdown_socket(socket[1], 1, 1); 202 os_shutdown_socket(socket[1], 1, 1);
203 os_close_file(socket[1]); 203 os_close_file(socket[1]);
204 out_close: 204 out_close:
205 os_close_file(new); 205 os_close_file(new);
206 return(err); 206 return err;
207} 207}
208
209/*
210 * Overrides for Emacs so that we follow Linus's tabbing style.
211 * Emacs will notice this stuff at the end of the file and automatically
212 * adjust the settings for this buffer only. This must remain at the end
213 * of the file.
214 * ---------------------------------------------------------------------------
215 * Local variables:
216 * c-file-style: "linux"
217 * End:
218 */
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 73b2bdd6d2d3..e942e836f995 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -78,6 +78,7 @@ static const struct file_operations rng_chrdev_ops = {
78 .read = rng_dev_read, 78 .read = rng_dev_read,
79}; 79};
80 80
81/* rng_init shouldn't be called more than once at boot time */
81static struct miscdevice rng_miscdev = { 82static struct miscdevice rng_miscdev = {
82 RNG_MISCDEV_MINOR, 83 RNG_MISCDEV_MINOR,
83 RNG_MODULE_NAME, 84 RNG_MODULE_NAME,
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index ed9c59082d0d..fc22b9bd9153 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -38,6 +38,7 @@ static void ssl_announce(char *dev_name, int dev)
38 dev_name); 38 dev_name);
39} 39}
40 40
41/* Almost const, except that xterm_title may be changed in an initcall */
41static struct chan_opts opts = { 42static struct chan_opts opts = {
42 .announce = ssl_announce, 43 .announce = ssl_announce,
43 .xterm_title = "Serial Line #%d", 44 .xterm_title = "Serial Line #%d",
@@ -46,10 +47,12 @@ static struct chan_opts opts = {
46 .in_kernel = 1, 47 .in_kernel = 1,
47}; 48};
48 49
49static int ssl_config(char *str); 50static int ssl_config(char *str, char **error_out);
50static int ssl_get_config(char *dev, char *str, int size, char **error_out); 51static int ssl_get_config(char *dev, char *str, int size, char **error_out);
51static int ssl_remove(int n); 52static int ssl_remove(int n, char **error_out);
52 53
54
55/* Const, except for .mc.list */
53static struct line_driver driver = { 56static struct line_driver driver = {
54 .name = "UML serial line", 57 .name = "UML serial line",
55 .device_name = "ttyS", 58 .device_name = "ttyS",
@@ -61,9 +64,8 @@ static struct line_driver driver = {
61 .read_irq_name = "ssl", 64 .read_irq_name = "ssl",
62 .write_irq = SSL_WRITE_IRQ, 65 .write_irq = SSL_WRITE_IRQ,
63 .write_irq_name = "ssl-write", 66 .write_irq_name = "ssl-write",
64 .symlink_from = "serial",
65 .symlink_to = "tts",
66 .mc = { 67 .mc = {
68 .list = LIST_HEAD_INIT(driver.mc.list),
67 .name = "ssl", 69 .name = "ssl",
68 .config = ssl_config, 70 .config = ssl_config,
69 .get_config = ssl_get_config, 71 .get_config = ssl_get_config,
@@ -72,17 +74,16 @@ static struct line_driver driver = {
72 }, 74 },
73}; 75};
74 76
75/* The array is initialized by line_init, which is an initcall. The 77/* The array is initialized by line_init, at initcall time. The
76 * individual elements are protected by individual semaphores. 78 * elements are locked individually as needed.
77 */ 79 */
78static struct line serial_lines[NR_PORTS] = 80static struct line serial_lines[NR_PORTS] =
79 { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; 81 { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
80 82
81static struct lines lines = LINES_INIT(NR_PORTS); 83static int ssl_config(char *str, char **error_out)
82
83static int ssl_config(char *str)
84{ 84{
85 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts); 85 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts,
86 error_out);
86} 87}
87 88
88static int ssl_get_config(char *dev, char *str, int size, char **error_out) 89static int ssl_get_config(char *dev, char *str, int size, char **error_out)
@@ -91,9 +92,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out)
91 size, error_out); 92 size, error_out);
92} 93}
93 94
94static int ssl_remove(int n) 95static int ssl_remove(int n, char **error_out)
95{ 96{
96 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); 97 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n,
98 error_out);
97} 99}
98 100
99static int ssl_open(struct tty_struct *tty, struct file *filp) 101static int ssl_open(struct tty_struct *tty, struct file *filp)
@@ -168,9 +170,10 @@ static int ssl_console_setup(struct console *co, char *options)
168{ 170{
169 struct line *line = &serial_lines[co->index]; 171 struct line *line = &serial_lines[co->index];
170 172
171 return console_open_chan(line, co, &opts); 173 return console_open_chan(line, co);
172} 174}
173 175
176/* No locking for register_console call - relies on single-threaded initcalls */
174static struct console ssl_cons = { 177static struct console ssl_cons = {
175 .name = "ttyS", 178 .name = "ttyS",
176 .write = ssl_console_write, 179 .write = ssl_console_write,
@@ -186,9 +189,8 @@ static int ssl_init(void)
186 189
187 printk(KERN_INFO "Initializing software serial port version %d\n", 190 printk(KERN_INFO "Initializing software serial port version %d\n",
188 ssl_version); 191 ssl_version);
189 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, 192 ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
190 serial_lines, 193 ARRAY_SIZE(serial_lines));
191 ARRAY_SIZE(serial_lines));
192 194
193 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); 195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
194 196
@@ -212,7 +214,15 @@ __uml_exitcall(ssl_exit);
212 214
213static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
214{ 216{
215 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str); 217 char *error;
218 int ret;
219
220 ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
221 if(ret < 0)
222 printk(KERN_ERR "Failed to set up serial line with "
223 "configuration string \"%s\" : %s\n", str, error);
224
225 return 1;
216} 226}
217 227
218__setup("ssl", ssl_chan_setup); 228__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 7a4897e27f42..7ff0b0fc37e7 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -30,8 +30,6 @@
30 30
31#define MAX_TTYS (16) 31#define MAX_TTYS (16)
32 32
33/* ----------------------------------------------------------------------------- */
34
35/* Referenced only by tty_driver below - presumably it's locked correctly 33/* Referenced only by tty_driver below - presumably it's locked correctly
36 * by the tty driver. 34 * by the tty driver.
37 */ 35 */
@@ -44,6 +42,7 @@ void stdio_announce(char *dev_name, int dev)
44 dev_name); 42 dev_name);
45} 43}
46 44
45/* Almost const, except that xterm_title may be changed in an initcall */
47static struct chan_opts opts = { 46static struct chan_opts opts = {
48 .announce = stdio_announce, 47 .announce = stdio_announce,
49 .xterm_title = "Virtual Console #%d", 48 .xterm_title = "Virtual Console #%d",
@@ -52,10 +51,12 @@ static struct chan_opts opts = {
52 .in_kernel = 1, 51 .in_kernel = 1,
53}; 52};
54 53
55static int con_config(char *str); 54static int con_config(char *str, char **error_out);
56static int con_get_config(char *dev, char *str, int size, char **error_out); 55static int con_get_config(char *dev, char *str, int size, char **error_out);
57static int con_remove(int n); 56static int con_remove(int n, char **con_remove);
57
58 58
59/* Const, except for .mc.list */
59static struct line_driver driver = { 60static struct line_driver driver = {
60 .name = "UML console", 61 .name = "UML console",
61 .device_name = "tty", 62 .device_name = "tty",
@@ -67,9 +68,8 @@ static struct line_driver driver = {
67 .read_irq_name = "console", 68 .read_irq_name = "console",
68 .write_irq = CONSOLE_WRITE_IRQ, 69 .write_irq = CONSOLE_WRITE_IRQ,
69 .write_irq_name = "console-write", 70 .write_irq_name = "console-write",
70 .symlink_from = "ttys",
71 .symlink_to = "vc",
72 .mc = { 71 .mc = {
72 .list = LIST_HEAD_INIT(driver.mc.list),
73 .name = "con", 73 .name = "con",
74 .config = con_config, 74 .config = con_config,
75 .get_config = con_get_config, 75 .get_config = con_get_config,
@@ -78,18 +78,16 @@ static struct line_driver driver = {
78 }, 78 },
79}; 79};
80 80
81static struct lines console_lines = LINES_INIT(MAX_TTYS); 81/* The array is initialized by line_init, at initcall time. The
82 82 * elements are locked individually as needed.
83/* The array is initialized by line_init, which is an initcall. The
84 * individual elements are protected by individual semaphores.
85 */ 83 */
86struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 84static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
87 [ 1 ... MAX_TTYS - 1 ] = 85 [ 1 ... MAX_TTYS - 1 ] =
88 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 86 LINE_INIT(CONFIG_CON_CHAN, &driver) };
89 87
90static int con_config(char *str) 88static int con_config(char *str, char **error_out)
91{ 89{
92 return line_config(vts, ARRAY_SIZE(vts), str, &opts); 90 return line_config(vts, ARRAY_SIZE(vts), str, &opts, error_out);
93} 91}
94 92
95static int con_get_config(char *dev, char *str, int size, char **error_out) 93static int con_get_config(char *dev, char *str, int size, char **error_out)
@@ -97,9 +95,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out)
97 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out); 95 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
98} 96}
99 97
100static int con_remove(int n) 98static int con_remove(int n, char **error_out)
101{ 99{
102 return line_remove(vts, ARRAY_SIZE(vts), n); 100 return line_remove(vts, ARRAY_SIZE(vts), n, error_out);
103} 101}
104 102
105static int con_open(struct tty_struct *tty, struct file *filp) 103static int con_open(struct tty_struct *tty, struct file *filp)
@@ -146,9 +144,10 @@ static int uml_console_setup(struct console *co, char *options)
146{ 144{
147 struct line *line = &vts[co->index]; 145 struct line *line = &vts[co->index];
148 146
149 return console_open_chan(line, co, &opts); 147 return console_open_chan(line, co);
150} 148}
151 149
150/* No locking for register_console call - relies on single-threaded initcalls */
152static struct console stdiocons = { 151static struct console stdiocons = {
153 .name = "tty", 152 .name = "tty",
154 .write = uml_console_write, 153 .write = uml_console_write,
@@ -156,16 +155,14 @@ static struct console stdiocons = {
156 .setup = uml_console_setup, 155 .setup = uml_console_setup,
157 .flags = CON_PRINTBUFFER, 156 .flags = CON_PRINTBUFFER,
158 .index = -1, 157 .index = -1,
159 .data = &vts,
160}; 158};
161 159
162int stdio_init(void) 160int stdio_init(void)
163{ 161{
164 char *new_title; 162 char *new_title;
165 163
166 console_driver = line_register_devfs(&console_lines, &driver, 164 console_driver = register_lines(&driver, &console_ops, vts,
167 &console_ops, vts, 165 ARRAY_SIZE(vts));
168 ARRAY_SIZE(vts));
169 if (console_driver == NULL) 166 if (console_driver == NULL)
170 return -1; 167 return -1;
171 printk(KERN_INFO "Initialized stdio console driver\n"); 168 printk(KERN_INFO "Initialized stdio console driver\n");
@@ -192,7 +189,15 @@ __uml_exitcall(console_exit);
192 189
193static int console_chan_setup(char *str) 190static int console_chan_setup(char *str)
194{ 191{
195 return line_setup(vts, ARRAY_SIZE(vts), str); 192 char *error;
193 int ret;
194
195 ret = line_setup(vts, ARRAY_SIZE(vts), str, &error);
196 if(ret < 0)
197 printk(KERN_ERR "Failed to set up console with "
198 "configuration string \"%s\" : %s\n", str, error);
199
200 return 1;
196} 201}
197__setup("con", console_chan_setup); 202__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 203__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 49c047b75cc5..f98d26e51381 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -56,6 +56,7 @@
56enum ubd_req { UBD_READ, UBD_WRITE }; 56enum ubd_req { UBD_READ, UBD_WRITE };
57 57
58struct io_thread_req { 58struct io_thread_req {
59 struct request *req;
59 enum ubd_req op; 60 enum ubd_req op;
60 int fds[2]; 61 int fds[2];
61 unsigned long offsets[2]; 62 unsigned long offsets[2];
@@ -106,10 +107,6 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
106 107
107#define DRIVER_NAME "uml-blkdev" 108#define DRIVER_NAME "uml-blkdev"
108 109
109/* Can be taken in interrupt context, and is passed to the block layer to lock
110 * the request queue. Kernel side code knows that. */
111static DEFINE_SPINLOCK(ubd_io_lock);
112
113static DEFINE_MUTEX(ubd_lock); 110static DEFINE_MUTEX(ubd_lock);
114 111
115/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and 112/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and
@@ -132,12 +129,8 @@ static struct block_device_operations ubd_blops = {
132 .getgeo = ubd_getgeo, 129 .getgeo = ubd_getgeo,
133}; 130};
134 131
135/* Protected by the queue_lock */
136static request_queue_t *ubd_queue;
137
138/* Protected by ubd_lock */ 132/* Protected by ubd_lock */
139static int fake_major = MAJOR_NR; 133static int fake_major = MAJOR_NR;
140
141static struct gendisk *ubd_gendisk[MAX_DEV]; 134static struct gendisk *ubd_gendisk[MAX_DEV];
142static struct gendisk *fake_gendisk[MAX_DEV]; 135static struct gendisk *fake_gendisk[MAX_DEV];
143 136
@@ -148,10 +141,6 @@ static struct gendisk *fake_gendisk[MAX_DEV];
148#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \ 141#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \
149 .cl = 1 }) 142 .cl = 1 })
150#endif 143#endif
151
152/* Not protected - changed only in ubd_setup_common and then only to
153 * to enable O_SYNC.
154 */
155static struct openflags global_openflags = OPEN_FLAGS; 144static struct openflags global_openflags = OPEN_FLAGS;
156 145
157struct cow { 146struct cow {
@@ -178,6 +167,8 @@ struct ubd {
178 unsigned no_cow:1; 167 unsigned no_cow:1;
179 struct cow cow; 168 struct cow cow;
180 struct platform_device pdev; 169 struct platform_device pdev;
170 struct request_queue *queue;
171 spinlock_t lock;
181}; 172};
182 173
183#define DEFAULT_COW { \ 174#define DEFAULT_COW { \
@@ -198,8 +189,10 @@ struct ubd {
198 .no_cow = 0, \ 189 .no_cow = 0, \
199 .shared = 0, \ 190 .shared = 0, \
200 .cow = DEFAULT_COW, \ 191 .cow = DEFAULT_COW, \
192 .lock = SPIN_LOCK_UNLOCKED, \
201} 193}
202 194
195/* Protected by ubd_lock */
203struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; 196struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
204 197
205/* Only changed by fake_ide_setup which is a setup */ 198/* Only changed by fake_ide_setup which is a setup */
@@ -242,7 +235,6 @@ static void make_ide_entries(char *dev_name)
242 235
243 ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); 236 ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
244 if(!ent) return; 237 if(!ent) return;
245 ent->nlink = 1;
246 ent->data = NULL; 238 ent->data = NULL;
247 ent->read_proc = proc_ide_read_media; 239 ent->read_proc = proc_ide_read_media;
248 ent->write_proc = NULL; 240 ent->write_proc = NULL;
@@ -286,12 +278,12 @@ static int parse_unit(char **ptr)
286 * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it 278 * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it
287 * should not be freed on exit. 279 * should not be freed on exit.
288 */ 280 */
289static int ubd_setup_common(char *str, int *index_out) 281static int ubd_setup_common(char *str, int *index_out, char **error_out)
290{ 282{
291 struct ubd *ubd_dev; 283 struct ubd *ubd_dev;
292 struct openflags flags = global_openflags; 284 struct openflags flags = global_openflags;
293 char *backing_file; 285 char *backing_file;
294 int n, err, i; 286 int n, err = 0, i;
295 287
296 if(index_out) *index_out = -1; 288 if(index_out) *index_out = -1;
297 n = *str; 289 n = *str;
@@ -302,56 +294,55 @@ static int ubd_setup_common(char *str, int *index_out)
302 str++; 294 str++;
303 if(!strcmp(str, "sync")){ 295 if(!strcmp(str, "sync")){
304 global_openflags = of_sync(global_openflags); 296 global_openflags = of_sync(global_openflags);
305 return(0); 297 goto out1;
306 } 298 }
299
300 err = -EINVAL;
307 major = simple_strtoul(str, &end, 0); 301 major = simple_strtoul(str, &end, 0);
308 if((*end != '\0') || (end == str)){ 302 if((*end != '\0') || (end == str)){
309 printk(KERN_ERR 303 *error_out = "Didn't parse major number";
310 "ubd_setup : didn't parse major number\n"); 304 goto out1;
311 return(1);
312 } 305 }
313 306
314 err = 1; 307 mutex_lock(&ubd_lock);
315 mutex_lock(&ubd_lock); 308 if(fake_major != MAJOR_NR){
316 if(fake_major != MAJOR_NR){ 309 *error_out = "Can't assign a fake major twice";
317 printk(KERN_ERR "Can't assign a fake major twice\n"); 310 goto out1;
318 goto out1; 311 }
319 }
320 312
321 fake_major = major; 313 fake_major = major;
322 314
323 printk(KERN_INFO "Setting extra ubd major number to %d\n", 315 printk(KERN_INFO "Setting extra ubd major number to %d\n",
324 major); 316 major);
325 err = 0; 317 err = 0;
326 out1: 318 out1:
327 mutex_unlock(&ubd_lock); 319 mutex_unlock(&ubd_lock);
328 return(err); 320 return err;
329 } 321 }
330 322
331 n = parse_unit(&str); 323 n = parse_unit(&str);
332 if(n < 0){ 324 if(n < 0){
333 printk(KERN_ERR "ubd_setup : couldn't parse unit number " 325 *error_out = "Couldn't parse device number";
334 "'%s'\n", str); 326 return -EINVAL;
335 return(1);
336 } 327 }
337 if(n >= MAX_DEV){ 328 if(n >= MAX_DEV){
338 printk(KERN_ERR "ubd_setup : index %d out of range " 329 *error_out = "Device number out of range";
339 "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1); 330 return 1;
340 return(1);
341 } 331 }
342 332
343 err = 1; 333 err = -EBUSY;
344 mutex_lock(&ubd_lock); 334 mutex_lock(&ubd_lock);
345 335
346 ubd_dev = &ubd_devs[n]; 336 ubd_dev = &ubd_devs[n];
347 if(ubd_dev->file != NULL){ 337 if(ubd_dev->file != NULL){
348 printk(KERN_ERR "ubd_setup : device already configured\n"); 338 *error_out = "Device is already configured";
349 goto out; 339 goto out;
350 } 340 }
351 341
352 if (index_out) 342 if (index_out)
353 *index_out = n; 343 *index_out = n;
354 344
345 err = -EINVAL;
355 for (i = 0; i < sizeof("rscd="); i++) { 346 for (i = 0; i < sizeof("rscd="); i++) {
356 switch (*str) { 347 switch (*str) {
357 case 'r': 348 case 'r':
@@ -370,47 +361,54 @@ static int ubd_setup_common(char *str, int *index_out)
370 str++; 361 str++;
371 goto break_loop; 362 goto break_loop;
372 default: 363 default:
373 printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n"); 364 *error_out = "Expected '=' or flag letter "
365 "(r, s, c, or d)";
374 goto out; 366 goto out;
375 } 367 }
376 str++; 368 str++;
377 } 369 }
378 370
379 if (*str == '=') 371 if (*str == '=')
380 printk(KERN_ERR "ubd_setup : Too many flags specified\n"); 372 *error_out = "Too many flags specified";
381 else 373 else
382 printk(KERN_ERR "ubd_setup : Expected '='\n"); 374 *error_out = "Missing '='";
383 goto out; 375 goto out;
384 376
385break_loop: 377break_loop:
386 err = 0;
387 backing_file = strchr(str, ','); 378 backing_file = strchr(str, ',');
388 379
389 if (!backing_file) { 380 if (backing_file == NULL)
390 backing_file = strchr(str, ':'); 381 backing_file = strchr(str, ':');
391 }
392 382
393 if(backing_file){ 383 if(backing_file != NULL){
394 if(ubd_dev->no_cow) 384 if(ubd_dev->no_cow){
395 printk(KERN_ERR "Can't specify both 'd' and a " 385 *error_out = "Can't specify both 'd' and a cow file";
396 "cow file\n"); 386 goto out;
387 }
397 else { 388 else {
398 *backing_file = '\0'; 389 *backing_file = '\0';
399 backing_file++; 390 backing_file++;
400 } 391 }
401 } 392 }
393 err = 0;
402 ubd_dev->file = str; 394 ubd_dev->file = str;
403 ubd_dev->cow.file = backing_file; 395 ubd_dev->cow.file = backing_file;
404 ubd_dev->boot_openflags = flags; 396 ubd_dev->boot_openflags = flags;
405out: 397out:
406 mutex_unlock(&ubd_lock); 398 mutex_unlock(&ubd_lock);
407 return(err); 399 return err;
408} 400}
409 401
410static int ubd_setup(char *str) 402static int ubd_setup(char *str)
411{ 403{
412 ubd_setup_common(str, NULL); 404 char *error;
413 return(1); 405 int err;
406
407 err = ubd_setup_common(str, NULL, &error);
408 if(err)
409 printk(KERN_ERR "Failed to initialize device with \"%s\" : "
410 "%s\n", str, error);
411 return 1;
414} 412}
415 413
416__setup("ubd", ubd_setup); 414__setup("ubd", ubd_setup);
@@ -422,7 +420,7 @@ __uml_help(ubd_setup,
422" use either a ':' or a ',': the first one allows writing things like;\n" 420" use either a ':' or a ',': the first one allows writing things like;\n"
423" ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n" 421" ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n"
424" while with a ',' the shell would not expand the 2nd '~'.\n" 422" while with a ',' the shell would not expand the 2nd '~'.\n"
425" When using only one filename, UML will detect whether to thread it like\n" 423" When using only one filename, UML will detect whether to treat it like\n"
426" a COW file or a backing file. To override this detection, add the 'd'\n" 424" a COW file or a backing file. To override this detection, add the 'd'\n"
427" flag:\n" 425" flag:\n"
428" ubd0d=BackingFile\n" 426" ubd0d=BackingFile\n"
@@ -471,12 +469,6 @@ static void do_ubd_request(request_queue_t * q);
471/* Only changed by ubd_init, which is an initcall. */ 469/* Only changed by ubd_init, which is an initcall. */
472int thread_fd = -1; 470int thread_fd = -1;
473 471
474/* Changed by ubd_handler, which is serialized because interrupts only
475 * happen on CPU 0.
476 * XXX: currently unused.
477 */
478static int intr_count = 0;
479
480/* call ubd_finish if you need to serialize */ 472/* call ubd_finish if you need to serialize */
481static void __ubd_finish(struct request *req, int error) 473static void __ubd_finish(struct request *req, int error)
482{ 474{
@@ -499,36 +491,38 @@ static void __ubd_finish(struct request *req, int error)
499 * spin_lock_irq()/spin_lock_irqsave() */ 491 * spin_lock_irq()/spin_lock_irqsave() */
500static inline void ubd_finish(struct request *req, int error) 492static inline void ubd_finish(struct request *req, int error)
501{ 493{
502 spin_lock(&ubd_io_lock); 494 struct ubd *dev = req->rq_disk->private_data;
495
496 spin_lock(&dev->lock);
503 __ubd_finish(req, error); 497 __ubd_finish(req, error);
504 spin_unlock(&ubd_io_lock); 498 spin_unlock(&dev->lock);
505} 499}
506 500
507/* XXX - move this inside ubd_intr. */ 501/* XXX - move this inside ubd_intr. */
508/* Called without ubd_io_lock held, and only in interrupt context. */ 502/* Called without dev->lock held, and only in interrupt context. */
509static void ubd_handler(void) 503static void ubd_handler(void)
510{ 504{
511 struct io_thread_req req; 505 struct io_thread_req req;
512 struct request *rq = elv_next_request(ubd_queue); 506 struct request *rq;
507 struct ubd *dev;
513 int n; 508 int n;
514 509
515 do_ubd = 0; 510 do_ubd = 0;
516 intr_count++;
517 n = os_read_file(thread_fd, &req, sizeof(req)); 511 n = os_read_file(thread_fd, &req, sizeof(req));
518 if(n != sizeof(req)){ 512 if(n != sizeof(req)){
519 printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " 513 printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
520 "err = %d\n", os_getpid(), -n); 514 "err = %d\n", os_getpid(), -n);
521 spin_lock(&ubd_io_lock);
522 end_request(rq, 0);
523 spin_unlock(&ubd_io_lock);
524 return; 515 return;
525 } 516 }
526 517
518 rq = req.req;
519 dev = rq->rq_disk->private_data;
520
527 ubd_finish(rq, req.error); 521 ubd_finish(rq, req.error);
528 reactivate_fd(thread_fd, UBD_IRQ); 522 reactivate_fd(thread_fd, UBD_IRQ);
529 spin_lock(&ubd_io_lock); 523 spin_lock(&dev->lock);
530 do_ubd_request(ubd_queue); 524 do_ubd_request(dev->queue);
531 spin_unlock(&ubd_io_lock); 525 spin_unlock(&dev->lock);
532} 526}
533 527
534static irqreturn_t ubd_intr(int irq, void *dev) 528static irqreturn_t ubd_intr(int irq, void *dev)
@@ -632,8 +626,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
632} 626}
633 627
634static int ubd_disk_register(int major, u64 size, int unit, 628static int ubd_disk_register(int major, u64 size, int unit,
635 struct gendisk **disk_out) 629 struct gendisk **disk_out)
636
637{ 630{
638 struct gendisk *disk; 631 struct gendisk *disk;
639 632
@@ -659,7 +652,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
659 } 652 }
660 653
661 disk->private_data = &ubd_devs[unit]; 654 disk->private_data = &ubd_devs[unit];
662 disk->queue = ubd_queue; 655 disk->queue = ubd_devs[unit].queue;
663 add_disk(disk); 656 add_disk(disk);
664 657
665 *disk_out = disk; 658 *disk_out = disk;
@@ -668,28 +661,39 @@ static int ubd_disk_register(int major, u64 size, int unit,
668 661
669#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9)) 662#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))
670 663
671static int ubd_add(int n) 664static int ubd_add(int n, char **error_out)
672{ 665{
673 struct ubd *ubd_dev = &ubd_devs[n]; 666 struct ubd *ubd_dev = &ubd_devs[n];
674 int err; 667 int err = 0;
675 668
676 err = -ENODEV;
677 if(ubd_dev->file == NULL) 669 if(ubd_dev->file == NULL)
678 goto out; 670 goto out;
679 671
680 err = ubd_file_size(ubd_dev, &ubd_dev->size); 672 err = ubd_file_size(ubd_dev, &ubd_dev->size);
681 if(err < 0) 673 if(err < 0){
674 *error_out = "Couldn't determine size of device's file";
682 goto out; 675 goto out;
676 }
683 677
684 ubd_dev->size = ROUND_BLOCK(ubd_dev->size); 678 ubd_dev->size = ROUND_BLOCK(ubd_dev->size);
685 679
686 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); 680 err = -ENOMEM;
687 if(err) 681 ubd_dev->queue = blk_init_queue(do_ubd_request, &ubd_dev->lock);
682 if (ubd_dev->queue == NULL) {
683 *error_out = "Failed to initialize device queue";
688 goto out; 684 goto out;
685 }
686 ubd_dev->queue->queuedata = ubd_dev;
687
688 err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]);
689 if(err){
690 *error_out = "Failed to register device";
691 goto out_cleanup;
692 }
689 693
690 if(fake_major != MAJOR_NR) 694 if(fake_major != MAJOR_NR)
691 ubd_disk_register(fake_major, ubd_dev->size, n, 695 ubd_disk_register(fake_major, ubd_dev->size, n,
692 &fake_gendisk[n]); 696 &fake_gendisk[n]);
693 697
694 /* perhaps this should also be under the "if (fake_major)" above */ 698 /* perhaps this should also be under the "if (fake_major)" above */
695 /* using the fake_disk->disk_name and also the fakehd_set name */ 699 /* using the fake_disk->disk_name and also the fakehd_set name */
@@ -699,30 +703,37 @@ static int ubd_add(int n)
699 err = 0; 703 err = 0;
700out: 704out:
701 return err; 705 return err;
706
707out_cleanup:
708 blk_cleanup_queue(ubd_dev->queue);
709 goto out;
702} 710}
703 711
704static int ubd_config(char *str) 712static int ubd_config(char *str, char **error_out)
705{ 713{
706 int n, ret; 714 int n, ret;
707 715
716 /* This string is possibly broken up and stored, so it's only
717 * freed if ubd_setup_common fails, or if only general options
718 * were set.
719 */
708 str = kstrdup(str, GFP_KERNEL); 720 str = kstrdup(str, GFP_KERNEL);
709 if (str == NULL) { 721 if (str == NULL) {
710 printk(KERN_ERR "ubd_config failed to strdup string\n"); 722 *error_out = "Failed to allocate memory";
711 ret = 1; 723 return -ENOMEM;
712 goto out;
713 } 724 }
714 ret = ubd_setup_common(str, &n); 725
715 if (ret) { 726 ret = ubd_setup_common(str, &n, error_out);
716 ret = -1; 727 if (ret)
717 goto err_free; 728 goto err_free;
718 } 729
719 if (n == -1) { 730 if (n == -1) {
720 ret = 0; 731 ret = 0;
721 goto err_free; 732 goto err_free;
722 } 733 }
723 734
724 mutex_lock(&ubd_lock); 735 mutex_lock(&ubd_lock);
725 ret = ubd_add(n); 736 ret = ubd_add(n, error_out);
726 if (ret) 737 if (ret)
727 ubd_devs[n].file = NULL; 738 ubd_devs[n].file = NULL;
728 mutex_unlock(&ubd_lock); 739 mutex_unlock(&ubd_lock);
@@ -777,7 +788,7 @@ static int ubd_id(char **str, int *start_out, int *end_out)
777 return n; 788 return n;
778} 789}
779 790
780static int ubd_remove(int n) 791static int ubd_remove(int n, char **error_out)
781{ 792{
782 struct ubd *ubd_dev; 793 struct ubd *ubd_dev;
783 int err = -ENODEV; 794 int err = -ENODEV;
@@ -807,6 +818,7 @@ static int ubd_remove(int n)
807 fake_gendisk[n] = NULL; 818 fake_gendisk[n] = NULL;
808 } 819 }
809 820
821 blk_cleanup_queue(ubd_dev->queue);
810 platform_device_unregister(&ubd_dev->pdev); 822 platform_device_unregister(&ubd_dev->pdev);
811 *ubd_dev = ((struct ubd) DEFAULT_UBD); 823 *ubd_dev = ((struct ubd) DEFAULT_UBD);
812 err = 0; 824 err = 0;
@@ -815,8 +827,11 @@ out:
815 return err; 827 return err;
816} 828}
817 829
818/* All these are called by mconsole in process context and without ubd-specific locks. */ 830/* All these are called by mconsole in process context and without
831 * ubd-specific locks. The structure itself is const except for .list.
832 */
819static struct mc_device ubd_mc = { 833static struct mc_device ubd_mc = {
834 .list = LIST_HEAD_INIT(ubd_mc.list),
820 .name = "ubd", 835 .name = "ubd",
821 .config = ubd_config, 836 .config = ubd_config,
822 .get_config = ubd_get_config, 837 .get_config = ubd_get_config,
@@ -836,13 +851,17 @@ static int __init ubd0_init(void)
836{ 851{
837 struct ubd *ubd_dev = &ubd_devs[0]; 852 struct ubd *ubd_dev = &ubd_devs[0];
838 853
854 mutex_lock(&ubd_lock);
839 if(ubd_dev->file == NULL) 855 if(ubd_dev->file == NULL)
840 ubd_dev->file = "root_fs"; 856 ubd_dev->file = "root_fs";
857 mutex_unlock(&ubd_lock);
858
841 return(0); 859 return(0);
842} 860}
843 861
844__initcall(ubd0_init); 862__initcall(ubd0_init);
845 863
864/* Used in ubd_init, which is an initcall */
846static struct platform_driver ubd_driver = { 865static struct platform_driver ubd_driver = {
847 .driver = { 866 .driver = {
848 .name = DRIVER_NAME, 867 .name = DRIVER_NAME,
@@ -851,17 +870,12 @@ static struct platform_driver ubd_driver = {
851 870
852static int __init ubd_init(void) 871static int __init ubd_init(void)
853{ 872{
854 int i; 873 char *error;
874 int i, err;
855 875
856 if (register_blkdev(MAJOR_NR, "ubd")) 876 if (register_blkdev(MAJOR_NR, "ubd"))
857 return -1; 877 return -1;
858 878
859 ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock);
860 if (!ubd_queue) {
861 unregister_blkdev(MAJOR_NR, "ubd");
862 return -1;
863 }
864
865 if (fake_major != MAJOR_NR) { 879 if (fake_major != MAJOR_NR) {
866 char name[sizeof("ubd_nnn\0")]; 880 char name[sizeof("ubd_nnn\0")];
867 881
@@ -870,8 +884,14 @@ static int __init ubd_init(void)
870 return -1; 884 return -1;
871 } 885 }
872 platform_driver_register(&ubd_driver); 886 platform_driver_register(&ubd_driver);
873 for (i = 0; i < MAX_DEV; i++) 887 mutex_lock(&ubd_lock);
874 ubd_add(i); 888 for (i = 0; i < MAX_DEV; i++){
889 err = ubd_add(i, &error);
890 if(err)
891 printk(KERN_ERR "Failed to initialize ubd device %d :"
892 "%s\n", i, error);
893 }
894 mutex_unlock(&ubd_lock);
875 return 0; 895 return 0;
876} 896}
877 897
@@ -1003,7 +1023,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
1003 req->bitmap_words, bitmap_len); 1023 req->bitmap_words, bitmap_len);
1004} 1024}
1005 1025
1006/* Called with ubd_io_lock held */ 1026/* Called with dev->lock held */
1007static int prepare_request(struct request *req, struct io_thread_req *io_req) 1027static int prepare_request(struct request *req, struct io_thread_req *io_req)
1008{ 1028{
1009 struct gendisk *disk = req->rq_disk; 1029 struct gendisk *disk = req->rq_disk;
@@ -1022,6 +1042,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1022 offset = ((__u64) req->sector) << 9; 1042 offset = ((__u64) req->sector) << 9;
1023 len = req->current_nr_sectors << 9; 1043 len = req->current_nr_sectors << 9;
1024 1044
1045 io_req->req = req;
1025 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; 1046 io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd;
1026 io_req->fds[1] = ubd_dev->fd; 1047 io_req->fds[1] = ubd_dev->fd;
1027 io_req->cow_offset = -1; 1048 io_req->cow_offset = -1;
@@ -1043,7 +1064,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
1043 return(0); 1064 return(0);
1044} 1065}
1045 1066
1046/* Called with ubd_io_lock held */ 1067/* Called with dev->lock held */
1047static void do_ubd_request(request_queue_t *q) 1068static void do_ubd_request(request_queue_t *q)
1048{ 1069{
1049 struct io_thread_req io_req; 1070 struct io_thread_req io_req;
@@ -1102,7 +1123,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1102 sizeof(ubd_id))) 1123 sizeof(ubd_id)))
1103 return(-EFAULT); 1124 return(-EFAULT);
1104 return(0); 1125 return(0);
1105 1126
1106 case CDROMVOLREAD: 1127 case CDROMVOLREAD:
1107 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume))) 1128 if(copy_from_user(&volume, (char __user *) arg, sizeof(volume)))
1108 return(-EFAULT); 1129 return(-EFAULT);
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 9003a343e148..c4b41bb1035f 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -30,14 +30,13 @@ struct chan {
30extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, 30extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
31 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
32extern int parse_chan_pair(char *str, struct line *line, int device, 32extern int parse_chan_pair(char *str, struct line *line, int device,
33 const struct chan_opts *opts); 33 const struct chan_opts *opts, char **error_out);
34extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
35extern int write_chan(struct list_head *chans, const char *buf, int len, 35extern int write_chan(struct list_head *chans, const char *buf, int len,
36 int write_irq); 36 int write_irq);
37extern int console_write_chan(struct list_head *chans, const char *buf, 37extern int console_write_chan(struct list_head *chans, const char *buf,
38 int len); 38 int len);
39extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co);
40 const struct chan_opts *opts);
41extern void deactivate_chan(struct list_head *chans, int irq); 40extern void deactivate_chan(struct list_head *chans, int irq);
42extern void reactivate_chan(struct list_head *chans, int irq); 41extern void reactivate_chan(struct list_head *chans, int irq);
43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 42extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index a795547a1dbd..38f16d812e7c 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -9,11 +9,11 @@
9#include "init.h" 9#include "init.h"
10 10
11struct chan_opts { 11struct chan_opts {
12 void (*announce)(char *dev_name, int dev); 12 void (*const announce)(char *dev_name, int dev);
13 char *xterm_title; 13 char *xterm_title;
14 int raw; 14 const int raw;
15 unsigned long tramp_stack; 15 const unsigned long tramp_stack;
16 int in_kernel; 16 const int in_kernel;
17}; 17};
18 18
19enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; 19enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
@@ -54,14 +54,3 @@ __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
54); 54);
55 55
56#endif 56#endif
57
58/*
59 * Overrides for Emacs so that we follow Linus's tabbing style.
60 * Emacs will notice this stuff at the end of the file and automatically
61 * adjust the settings for this buffer only. This must remain at the end
62 * of the file.
63 * ---------------------------------------------------------------------------
64 * Local variables:
65 * c-file-style: "linux"
66 * End:
67 */
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index cec9fcc57bf5..173af029d12b 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -61,7 +61,6 @@ extern int set_signals(int enable);
61extern void force_sigbus(void); 61extern void force_sigbus(void);
62extern int pid_to_processor_id(int pid); 62extern int pid_to_processor_id(int pid);
63extern void deliver_signals(void *t); 63extern void deliver_signals(void *t);
64extern int next_syscall_index(int max);
65extern int next_trap_index(int max); 64extern int next_trap_index(int max);
66extern void default_idle(void); 65extern void default_idle(void);
67extern void finish_fork(void); 66extern void finish_fork(void);
@@ -88,7 +87,6 @@ extern void timer_irq(union uml_pt_regs *regs);
88extern void unprotect_stack(unsigned long stack); 87extern void unprotect_stack(unsigned long stack);
89extern void do_uml_exitcalls(void); 88extern void do_uml_exitcalls(void);
90extern int attach_debugger(int idle_pid, int pid, int stop); 89extern int attach_debugger(int idle_pid, int pid, int stop);
91extern void bad_segv(struct faultinfo fi, unsigned long ip);
92extern int config_gdb(char *str); 90extern int config_gdb(char *str);
93extern int remove_gdb(void); 91extern int remove_gdb(void);
94extern char *uml_strdup(char *string); 92extern char *uml_strdup(char *string);
@@ -104,8 +102,6 @@ extern int clear_user_proc(void *buf, int size);
104extern int copy_to_user_proc(void *to, void *from, int size); 102extern int copy_to_user_proc(void *to, void *from, int size);
105extern int copy_from_user_proc(void *to, void *from, int size); 103extern int copy_from_user_proc(void *to, void *from, int size);
106extern int strlen_user_proc(char *str); 104extern int strlen_user_proc(char *str);
107extern void bus_handler(int sig, union uml_pt_regs *regs);
108extern void winch(int sig, union uml_pt_regs *regs);
109extern long execute_syscall(void *r); 105extern long execute_syscall(void *r);
110extern int smp_sigio_handler(void); 106extern int smp_sigio_handler(void);
111extern void *get_current(void); 107extern void *get_current(void);
@@ -120,7 +116,6 @@ extern void time_init_kern(void);
120 116
121/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ 117/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
122extern int __cant_sleep(void); 118extern int __cant_sleep(void);
123extern void segv_handler(int sig, union uml_pt_regs *regs);
124extern void sigio_handler(int sig, union uml_pt_regs *regs); 119extern void sigio_handler(int sig, union uml_pt_regs *regs);
125 120
126#endif 121#endif
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5f232ae89fbb..1223f2c844b4 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -11,36 +11,37 @@
11#include "linux/tty.h" 11#include "linux/tty.h"
12#include "linux/interrupt.h" 12#include "linux/interrupt.h"
13#include "linux/spinlock.h" 13#include "linux/spinlock.h"
14#include "linux/mutex.h"
14#include "chan_user.h" 15#include "chan_user.h"
15#include "mconsole_kern.h" 16#include "mconsole_kern.h"
16 17
18/* There's only one modifiable field in this - .mc.list */
17struct line_driver { 19struct line_driver {
18 char *name; 20 const char *name;
19 char *device_name; 21 const char *device_name;
20 short major; 22 const short major;
21 short minor_start; 23 const short minor_start;
22 short type; 24 const short type;
23 short subtype; 25 const short subtype;
24 int read_irq; 26 const int read_irq;
25 char *read_irq_name; 27 const char *read_irq_name;
26 int write_irq; 28 const int write_irq;
27 char *write_irq_name; 29 const char *write_irq_name;
28 char *symlink_from;
29 char *symlink_to;
30 struct mc_device mc; 30 struct mc_device mc;
31}; 31};
32 32
33struct line { 33struct line {
34 struct tty_struct *tty; 34 struct tty_struct *tty;
35 spinlock_t count_lock;
36 int valid;
37
35 char *init_str; 38 char *init_str;
36 int init_pri; 39 int init_pri;
37 struct list_head chan_list; 40 struct list_head chan_list;
38 int valid; 41
39 int count;
40 int throttled;
41 /*This lock is actually, mostly, local to*/ 42 /*This lock is actually, mostly, local to*/
42 spinlock_t lock; 43 spinlock_t lock;
43 44 int throttled;
44 /* Yes, this is a real circular buffer. 45 /* Yes, this is a real circular buffer.
45 * XXX: And this should become a struct kfifo! 46 * XXX: And this should become a struct kfifo!
46 * 47 *
@@ -57,22 +58,17 @@ struct line {
57}; 58};
58 59
59#define LINE_INIT(str, d) \ 60#define LINE_INIT(str, d) \
60 { .init_str = str, \ 61 { .count_lock = SPIN_LOCK_UNLOCKED, \
62 .init_str = str, \
61 .init_pri = INIT_STATIC, \ 63 .init_pri = INIT_STATIC, \
62 .valid = 1, \ 64 .valid = 1, \
63 .lock = SPIN_LOCK_UNLOCKED, \ 65 .lock = SPIN_LOCK_UNLOCKED, \
64 .driver = d } 66 .driver = d }
65 67
66struct lines {
67 int num;
68};
69
70#define LINES_INIT(n) { .num = n }
71
72extern void line_close(struct tty_struct *tty, struct file * filp); 68extern void line_close(struct tty_struct *tty, struct file * filp);
73extern int line_open(struct line *lines, struct tty_struct *tty); 69extern int line_open(struct line *lines, struct tty_struct *tty);
74extern int line_setup(struct line *lines, unsigned int sizeof_lines, 70extern int line_setup(struct line *lines, unsigned int sizeof_lines,
75 char *init); 71 char *init, char **error_out);
76extern int line_write(struct tty_struct *tty, const unsigned char *buf, 72extern int line_write(struct tty_struct *tty, const unsigned char *buf,
77 int len); 73 int len);
78extern void line_put_char(struct tty_struct *tty, unsigned char ch); 74extern void line_put_char(struct tty_struct *tty, unsigned char ch);
@@ -90,17 +86,18 @@ extern char *add_xterm_umid(char *base);
90extern int line_setup_irq(int fd, int input, int output, struct line *line, 86extern int line_setup_irq(int fd, int input, int output, struct line *line,
91 void *data); 87 void *data);
92extern void line_close_chan(struct line *line); 88extern void line_close_chan(struct line *line);
93extern struct tty_driver * line_register_devfs(struct lines *set, 89extern struct tty_driver *register_lines(struct line_driver *line_driver,
94 struct line_driver *line_driver, 90 const struct tty_operations *driver,
95 const struct tty_operations *driver, 91 struct line *lines, int nlines);
96 struct line *lines, int nlines);
97extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); 92extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
98extern void close_lines(struct line *lines, int nlines); 93extern void close_lines(struct line *lines, int nlines);
99 94
100extern int line_config(struct line *lines, unsigned int sizeof_lines, 95extern int line_config(struct line *lines, unsigned int sizeof_lines,
101 char *str, const struct chan_opts *opts); 96 char *str, const struct chan_opts *opts,
97 char **error_out);
102extern int line_id(char **str, int *start_out, int *end_out); 98extern int line_id(char **str, int *start_out, int *end_out);
103extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 99extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n,
100 char **error_out);
104extern int line_get_config(char *dev, struct line *lines, 101extern int line_get_config(char *dev, struct line *lines,
105 unsigned int sizeof_lines, char *str, 102 unsigned int sizeof_lines, char *str,
106 int size, char **error_out); 103 int size, char **error_out);
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 1ea6d928e1cd..d2fe07e78958 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -18,10 +18,10 @@ struct mconsole_entry {
18struct mc_device { 18struct mc_device {
19 struct list_head list; 19 struct list_head list;
20 char *name; 20 char *name;
21 int (*config)(char *); 21 int (*config)(char *, char **);
22 int (*get_config)(char *, char *, int, char **); 22 int (*get_config)(char *, char *, int, char **);
23 int (*id)(char **, int *, int *); 23 int (*id)(char **, int *, int *);
24 int (*remove)(int); 24 int (*remove)(int, char **);
25}; 25};
26 26
27#define CONFIG_CHUNK(str, size, current, chunk, end) \ 27#define CONFIG_CHUNK(str, size, current, chunk, end) \
@@ -50,14 +50,3 @@ static inline void mconsole_register_dev(struct mc_device *new)
50#endif 50#endif
51 51
52#endif 52#endif
53
54/*
55 * 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
57 * adjust the settings for this buffer only. This must remain at the end
58 * of the file.
59 * ---------------------------------------------------------------------------
60 * Local variables:
61 * c-file-style: "linux"
62 * End:
63 */
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 218f8b47fdcd..125ab42df18a 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -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 */
@@ -36,7 +36,7 @@ struct uml_net_private {
36 void (*remove)(void *); 36 void (*remove)(void *);
37 int (*read)(int, struct sk_buff **skb, struct uml_net_private *); 37 int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
38 int (*write)(int, struct sk_buff **skb, struct uml_net_private *); 38 int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
39 39
40 void (*add_address)(unsigned char *, unsigned char *, void *); 40 void (*add_address)(unsigned char *, unsigned char *, void *);
41 void (*delete_address)(unsigned char *, unsigned char *, void *); 41 void (*delete_address)(unsigned char *, unsigned char *, void *);
42 int (*set_mtu)(int mtu, void *); 42 int (*set_mtu)(int mtu, void *);
@@ -52,18 +52,18 @@ struct net_kern_info {
52 52
53struct transport { 53struct transport {
54 struct list_head list; 54 struct list_head list;
55 char *name; 55 const char *name;
56 int (*setup)(char *, char **, void *); 56 int (* const setup)(char *, char **, void *);
57 const struct net_user_info *user; 57 const struct net_user_info *user;
58 const struct net_kern_info *kern; 58 const struct net_kern_info *kern;
59 int private_size; 59 const int private_size;
60 int setup_size; 60 const int setup_size;
61}; 61};
62 62
63extern struct net_device *ether_init(int); 63extern struct net_device *ether_init(int);
64extern unsigned short ether_protocol(struct sk_buff *); 64extern unsigned short ether_protocol(struct sk_buff *);
65extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); 65extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
66extern int tap_setup_common(char *str, char *type, char **dev_name, 66extern int tap_setup_common(char *str, char *type, char **dev_name,
67 char **mac_out, char **gate_addr); 67 char **mac_out, char **gate_addr);
68extern void register_transport(struct transport *new); 68extern void register_transport(struct transport *new);
69extern unsigned short eth_protocol(struct sk_buff *skb); 69extern unsigned short eth_protocol(struct sk_buff *skb);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 13a86bd383d3..8629bd191492 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -137,7 +137,6 @@ extern int os_new_tty_pgrp(int fd, int pid);
137extern int os_get_ifname(int fd, char *namebuf); 137extern int os_get_ifname(int fd, char *namebuf);
138extern int os_set_slip(int fd); 138extern int os_set_slip(int fd);
139extern int os_set_owner(int fd, int pid); 139extern int os_set_owner(int fd, int pid);
140extern int os_sigio_async(int master, int slave);
141extern int os_mode_fd(int fd, int mode); 140extern int os_mode_fd(int fd, int mode);
142 141
143extern int os_seek_file(int fd, __u64 offset); 142extern int os_seek_file(int fd, __u64 offset);
@@ -341,4 +340,6 @@ extern void maybe_sigio_broken(int fd, int read);
341extern void sig_handler_common_skas(int sig, void *sc_ptr); 340extern void sig_handler_common_skas(int sig, void *sc_ptr);
342extern void user_signal(int sig, union uml_pt_regs *regs, int pid); 341extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
343 342
343extern int os_arch_prctl(int pid, int code, unsigned long *addr);
344
344#endif 345#endif
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h
index fe99ea163c2e..434f1a9ae4b3 100644
--- a/arch/um/include/sigio.h
+++ b/arch/um/include/sigio.h
@@ -12,14 +12,3 @@ extern void sigio_lock(void);
12extern void sigio_unlock(void); 12extern void sigio_unlock(void);
13 13
14#endif 14#endif
15
16/*
17 * Overrides for Emacs so that we follow Linus's tabbing style.
18 * Emacs will notice this stuff at the end of the file and automatically
19 * adjust the settings for this buffer only. This must remain at the end
20 * of the file.
21 * ---------------------------------------------------------------------------
22 * Local variables:
23 * c-file-style: "linux"
24 * End:
25 */
diff --git a/arch/um/include/tempfile.h b/arch/um/include/tempfile.h
index e36d9e0f5105..d441eac936b9 100644
--- a/arch/um/include/tempfile.h
+++ b/arch/um/include/tempfile.h
@@ -9,13 +9,3 @@
9extern int make_tempfile(const char *template, char **tempname, int do_unlink); 9extern int make_tempfile(const char *template, char **tempname, int do_unlink);
10 10
11#endif 11#endif
12/*
13 * Overrides for Emacs so that we follow Linus's tabbing style.
14 * Emacs will notice this stuff at the end of the file and automatically
15 * adjust the settings for this buffer only. This must remain at the end
16 * of the file.
17 * ---------------------------------------------------------------------------
18 * Local variables:
19 * c-file-style: "linux"
20 * End:
21 */
diff --git a/arch/um/include/umid.h b/arch/um/include/umid.h
deleted file mode 100644
index 11373c851f15..000000000000
--- a/arch/um/include/umid.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __UMID_H__
7#define __UMID_H__
8
9extern int umid_file_name(char *name, char *buf, int len);
10
11#endif
12
13/*
14 * Overrides for Emacs so that we follow Linus's tabbing style.
15 * Emacs will notice this stuff at the end of the file and automatically
16 * adjust the settings for this buffer only. This must remain at the end
17 * of the file.
18 * ---------------------------------------------------------------------------
19 * Local variables:
20 * c-file-style: "linux"
21 * End:
22 */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 06625fefef33..023575f67343 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -38,8 +38,6 @@ extern unsigned long long highmem;
38 38
39extern char host_info[]; 39extern char host_info[];
40 40
41extern char saved_command_line[];
42
43extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; 41extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
44extern unsigned long _unprotected_end; 42extern unsigned long _unprotected_end;
45extern unsigned long brk_start; 43extern unsigned long brk_start;
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 6fa63a2a89e3..c5cf4a0827b0 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
7clean-files := 7clean-files :=
8 8
9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ 9obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
10 physmem.o process.o ptrace.o reboot.o resource.o sigio.o \ 10 physmem.o process.o ptrace.o reboot.o sigio.o \
11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ 11 signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
12 um_arch.o umid.o 12 um_arch.o umid.o
13 13
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8d56ec6cca79..121166400e25 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -39,9 +39,9 @@ static long execve1(char *file, char __user * __user *argv,
39 char __user *__user *env) 39 char __user *__user *env)
40{ 40{
41 long error; 41 long error;
42#ifdef CONFIG_TTY_LOG
42 struct tty_struct *tty; 43 struct tty_struct *tty;
43 44
44#ifdef CONFIG_TTY_LOG
45 mutex_lock(&tty_mutex); 45 mutex_lock(&tty_mutex);
46 tty = get_current_tty(); 46 tty = get_current_tty();
47 if (tty) 47 if (tty)
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 5c1e611f628d..50a288bb875a 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -79,7 +79,7 @@ skip:
79 return 0; 79 return 0;
80} 80}
81 81
82struct irq_fd *active_fds = NULL; 82static struct irq_fd *active_fds = NULL;
83static struct irq_fd **last_irq_ptr = &active_fds; 83static struct irq_fd **last_irq_ptr = &active_fds;
84 84
85extern void free_irqs(void); 85extern void free_irqs(void);
@@ -124,8 +124,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
124 if (err < 0) 124 if (err < 0)
125 goto out; 125 goto out;
126 126
127 new_fd = um_kmalloc(sizeof(*new_fd));
128 err = -ENOMEM; 127 err = -ENOMEM;
128 new_fd = kmalloc(sizeof(struct irq_fd), GFP_KERNEL);
129 if (new_fd == NULL) 129 if (new_fd == NULL)
130 goto out; 130 goto out;
131 131
@@ -176,9 +176,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
176 */ 176 */
177 spin_unlock_irqrestore(&irq_lock, flags); 177 spin_unlock_irqrestore(&irq_lock, flags);
178 kfree(tmp_pfd); 178 kfree(tmp_pfd);
179 tmp_pfd = NULL;
180 179
181 tmp_pfd = um_kmalloc(n); 180 tmp_pfd = kmalloc(n, GFP_KERNEL);
182 if (tmp_pfd == NULL) 181 if (tmp_pfd == NULL)
183 goto out_kfree; 182 goto out_kfree;
184 183
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index c95855ba6ab5..e85d65deea0d 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -24,8 +24,9 @@
24#include "init.h" 24#include "init.h"
25#include "kern_constants.h" 25#include "kern_constants.h"
26 26
27/* Changed during early boot */ 27/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
28unsigned long *empty_zero_page = NULL; 28unsigned long *empty_zero_page = NULL;
29/* allocated in paging_init and unchanged thereafter */
29unsigned long *empty_bad_page = NULL; 30unsigned long *empty_bad_page = NULL;
30pgd_t swapper_pg_dir[PTRS_PER_PGD]; 31pgd_t swapper_pg_dir[PTRS_PER_PGD];
31unsigned long long highmem; 32unsigned long long highmem;
@@ -65,8 +66,8 @@ void mem_init(void)
65{ 66{
66 max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT; 67 max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
67 68
68 /* clear the zero-page */ 69 /* clear the zero-page */
69 memset((void *) empty_zero_page, 0, PAGE_SIZE); 70 memset((void *) empty_zero_page, 0, PAGE_SIZE);
70 71
71 /* Map in the area just after the brk now that kmalloc is about 72 /* Map in the area just after the brk now that kmalloc is about
72 * to be turned on. 73 * to be turned on.
@@ -253,8 +254,10 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
253 int i; 254 int i;
254 255
255 again: 256 again:
256 if(page == NULL) return(page); 257 if(page == NULL)
257 if(PageHighMem(page)) return(page); 258 return page;
259 if(PageHighMem(page))
260 return page;
258 261
259 addr = (unsigned long) page_address(page); 262 addr = (unsigned long) page_address(page);
260 for(i = 0; i < (1 << order); i++){ 263 for(i = 0; i < (1 << order); i++){
@@ -263,13 +266,15 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
263 sizeof(zero), 266 sizeof(zero),
264 &current->thread.fault_addr, 267 &current->thread.fault_addr,
265 &current->thread.fault_catcher)){ 268 &current->thread.fault_catcher)){
266 if(!(mask & __GFP_WAIT)) return(NULL); 269 if(!(mask & __GFP_WAIT))
270 return NULL;
267 else break; 271 else break;
268 } 272 }
269 addr += PAGE_SIZE; 273 addr += PAGE_SIZE;
270 } 274 }
271 275
272 if(i == (1 << order)) return(page); 276 if(i == (1 << order))
277 return page;
273 page = alloc_pages(mask, order); 278 page = alloc_pages(mask, order);
274 goto again; 279 goto again;
275} 280}
@@ -283,7 +288,6 @@ void free_initmem(void)
283} 288}
284 289
285#ifdef CONFIG_BLK_DEV_INITRD 290#ifdef CONFIG_BLK_DEV_INITRD
286
287void free_initrd_mem(unsigned long start, unsigned long end) 291void free_initrd_mem(unsigned long start, unsigned long end)
288{ 292{
289 if (start < end) 293 if (start < end)
@@ -296,37 +300,36 @@ void free_initrd_mem(unsigned long start, unsigned long end)
296 totalram_pages++; 300 totalram_pages++;
297 } 301 }
298} 302}
299
300#endif 303#endif
301 304
302void show_mem(void) 305void show_mem(void)
303{ 306{
304 int pfn, total = 0, reserved = 0; 307 int pfn, total = 0, reserved = 0;
305 int shared = 0, cached = 0; 308 int shared = 0, cached = 0;
306 int highmem = 0; 309 int highmem = 0;
307 struct page *page; 310 struct page *page;
308 311
309 printk("Mem-info:\n"); 312 printk("Mem-info:\n");
310 show_free_areas(); 313 show_free_areas();
311 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); 314 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
312 pfn = max_mapnr; 315 pfn = max_mapnr;
313 while(pfn-- > 0) { 316 while(pfn-- > 0) {
314 page = pfn_to_page(pfn); 317 page = pfn_to_page(pfn);
315 total++; 318 total++;
316 if(PageHighMem(page)) 319 if(PageHighMem(page))
317 highmem++; 320 highmem++;
318 if(PageReserved(page)) 321 if(PageReserved(page))
319 reserved++; 322 reserved++;
320 else if(PageSwapCache(page)) 323 else if(PageSwapCache(page))
321 cached++; 324 cached++;
322 else if(page_count(page)) 325 else if(page_count(page))
323 shared += page_count(page) - 1; 326 shared += page_count(page) - 1;
324 } 327 }
325 printk("%d pages of RAM\n", total); 328 printk("%d pages of RAM\n", total);
326 printk("%d pages of HIGHMEM\n", highmem); 329 printk("%d pages of HIGHMEM\n", highmem);
327 printk("%d reserved pages\n", reserved); 330 printk("%d reserved pages\n", reserved);
328 printk("%d pages shared\n", shared); 331 printk("%d pages shared\n", shared);
329 printk("%d pages swap cached\n", cached); 332 printk("%d pages swap cached\n", cached);
330} 333}
331 334
332/* 335/*
@@ -362,28 +365,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
362struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) 365struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
363{ 366{
364 struct page *pte; 367 struct page *pte;
365 368
366 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); 369 pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
367 return pte; 370 return pte;
368} 371}
369
370struct iomem_region *iomem_regions = NULL;
371int iomem_size = 0;
372
373extern int parse_iomem(char *str, int *add) __init;
374
375__uml_setup("iomem=", parse_iomem,
376"iomem=<name>,<file>\n"
377" Configure <file> as an IO memory region named <name>.\n\n"
378);
379
380/*
381 * Overrides for Emacs so that we follow Linus's tabbing style.
382 * Emacs will notice this stuff at the end of the file and automatically
383 * adjust the settings for this buffer only. This must remain at the end
384 * of the file.
385 * ---------------------------------------------------------------------------
386 * Local variables:
387 * c-file-style: "linux"
388 * End:
389 */
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index abafa64b8727..638f3b5f6094 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -40,7 +40,7 @@ static struct rb_node **find_rb(void *virt)
40 while(*n != NULL){ 40 while(*n != NULL){
41 d = rb_entry(*n, struct phys_desc, rb); 41 d = rb_entry(*n, struct phys_desc, rb);
42 if(d->virt == virt) 42 if(d->virt == virt)
43 return(n); 43 return n;
44 44
45 if(d->virt > virt) 45 if(d->virt > virt)
46 n = &(*n)->rb_left; 46 n = &(*n)->rb_left;
@@ -48,7 +48,7 @@ static struct rb_node **find_rb(void *virt)
48 n = &(*n)->rb_right; 48 n = &(*n)->rb_right;
49 } 49 }
50 50
51 return(n); 51 return n;
52} 52}
53 53
54static struct phys_desc *find_phys_mapping(void *virt) 54static struct phys_desc *find_phys_mapping(void *virt)
@@ -56,9 +56,9 @@ static struct phys_desc *find_phys_mapping(void *virt)
56 struct rb_node **n = find_rb(virt); 56 struct rb_node **n = find_rb(virt);
57 57
58 if(*n == NULL) 58 if(*n == NULL)
59 return(NULL); 59 return NULL;
60 60
61 return(rb_entry(*n, struct phys_desc, rb)); 61 return rb_entry(*n, struct phys_desc, rb);
62} 62}
63 63
64static void insert_phys_mapping(struct phys_desc *desc) 64static void insert_phys_mapping(struct phys_desc *desc)
@@ -89,10 +89,10 @@ static struct desc_mapping *find_mapping(int fd)
89 list_for_each(ele, &descriptor_mappings){ 89 list_for_each(ele, &descriptor_mappings){
90 desc = list_entry(ele, struct desc_mapping, list); 90 desc = list_entry(ele, struct desc_mapping, list);
91 if(desc->fd == fd) 91 if(desc->fd == fd)
92 return(desc); 92 return desc;
93 } 93 }
94 94
95 return(NULL); 95 return NULL;
96} 96}
97 97
98static struct desc_mapping *descriptor_mapping(int fd) 98static struct desc_mapping *descriptor_mapping(int fd)
@@ -101,11 +101,11 @@ static struct desc_mapping *descriptor_mapping(int fd)
101 101
102 desc = find_mapping(fd); 102 desc = find_mapping(fd);
103 if(desc != NULL) 103 if(desc != NULL)
104 return(desc); 104 return desc;
105 105
106 desc = kmalloc(sizeof(*desc), GFP_ATOMIC); 106 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
107 if(desc == NULL) 107 if(desc == NULL)
108 return(NULL); 108 return NULL;
109 109
110 *desc = ((struct desc_mapping) 110 *desc = ((struct desc_mapping)
111 { .fd = fd, 111 { .fd = fd,
@@ -113,7 +113,7 @@ static struct desc_mapping *descriptor_mapping(int fd)
113 .pages = LIST_HEAD_INIT(desc->pages) }); 113 .pages = LIST_HEAD_INIT(desc->pages) });
114 list_add(&desc->list, &descriptor_mappings); 114 list_add(&desc->list, &descriptor_mappings);
115 115
116 return(desc); 116 return desc;
117} 117}
118 118
119int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) 119int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
@@ -125,11 +125,11 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
125 125
126 fd_maps = descriptor_mapping(fd); 126 fd_maps = descriptor_mapping(fd);
127 if(fd_maps == NULL) 127 if(fd_maps == NULL)
128 return(-ENOMEM); 128 return -ENOMEM;
129 129
130 phys = __pa(virt); 130 phys = __pa(virt);
131 desc = find_phys_mapping(virt); 131 desc = find_phys_mapping(virt);
132 if(desc != NULL) 132 if(desc != NULL)
133 panic("Address 0x%p is already substituted\n", virt); 133 panic("Address 0x%p is already substituted\n", virt);
134 134
135 err = -ENOMEM; 135 err = -ENOMEM;
@@ -155,7 +155,7 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
155 rb_erase(&desc->rb, &phys_mappings); 155 rb_erase(&desc->rb, &phys_mappings);
156 kfree(desc); 156 kfree(desc);
157 out: 157 out:
158 return(err); 158 return err;
159} 159}
160 160
161static int physmem_fd = -1; 161static int physmem_fd = -1;
@@ -182,10 +182,10 @@ int physmem_remove_mapping(void *virt)
182 virt = (void *) ((unsigned long) virt & PAGE_MASK); 182 virt = (void *) ((unsigned long) virt & PAGE_MASK);
183 desc = find_phys_mapping(virt); 183 desc = find_phys_mapping(virt);
184 if(desc == NULL) 184 if(desc == NULL)
185 return(0); 185 return 0;
186 186
187 remove_mapping(desc); 187 remove_mapping(desc);
188 return(1); 188 return 1;
189} 189}
190 190
191void physmem_forget_descriptor(int fd) 191void physmem_forget_descriptor(int fd)
@@ -239,9 +239,9 @@ void arch_free_page(struct page *page, int order)
239 239
240int is_remapped(void *virt) 240int is_remapped(void *virt)
241{ 241{
242 struct phys_desc *desc = find_phys_mapping(virt); 242 struct phys_desc *desc = find_phys_mapping(virt);
243 243
244 return(desc != NULL); 244 return desc != NULL;
245} 245}
246 246
247/* Changed during early boot */ 247/* Changed during early boot */
@@ -276,7 +276,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
276 else map = alloc_bootmem_low_pages(total_len); 276 else map = alloc_bootmem_low_pages(total_len);
277 277
278 if(map == NULL) 278 if(map == NULL)
279 return(-ENOMEM); 279 return -ENOMEM;
280 280
281 for(i = 0; i < total_pages; i++){ 281 for(i = 0; i < total_pages; i++){
282 p = &map[i]; 282 p = &map[i];
@@ -286,7 +286,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
286 } 286 }
287 287
288 max_mapnr = total_pages; 288 max_mapnr = total_pages;
289 return(0); 289 return 0;
290} 290}
291 291
292/* Changed during early boot */ 292/* Changed during early boot */
@@ -296,7 +296,7 @@ unsigned long get_kmem_end(void)
296{ 296{
297 if(kmem_top == 0) 297 if(kmem_top == 0)
298 kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); 298 kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
299 return(kmem_top); 299 return kmem_top;
300} 300}
301 301
302void map_memory(unsigned long virt, unsigned long phys, unsigned long len, 302void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
@@ -379,7 +379,7 @@ int phys_mapping(unsigned long phys, __u64 *offset_out)
379 *offset_out = phys - iomem_size; 379 *offset_out = phys - iomem_size;
380 } 380 }
381 381
382 return(fd); 382 return fd;
383} 383}
384 384
385static int __init uml_mem_setup(char *line, int *add) 385static int __init uml_mem_setup(char *line, int *add)
@@ -398,6 +398,23 @@ __uml_setup("mem=", uml_mem_setup,
398" Example: mem=64M\n\n" 398" Example: mem=64M\n\n"
399); 399);
400 400
401extern int __init parse_iomem(char *str, int *add);
402
403__uml_setup("iomem=", parse_iomem,
404"iomem=<name>,<file>\n"
405" Configure <file> as an IO memory region named <name>.\n\n"
406);
407
408/*
409 * This list is constructed in parse_iomem and addresses filled in in
410 * setup_iomem, both of which run during early boot. Afterwards, it's
411 * unchanged.
412 */
413struct iomem_region *iomem_regions = NULL;
414
415/* Initialized in parse_iomem */
416int iomem_size = 0;
417
401unsigned long find_iomem(char *driver, unsigned long *len_out) 418unsigned long find_iomem(char *driver, unsigned long *len_out)
402{ 419{
403 struct iomem_region *region = iomem_regions; 420 struct iomem_region *region = iomem_regions;
@@ -405,13 +422,13 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
405 while(region != NULL){ 422 while(region != NULL){
406 if(!strcmp(region->driver, driver)){ 423 if(!strcmp(region->driver, driver)){
407 *len_out = region->size; 424 *len_out = region->size;
408 return(region->virt); 425 return region->virt;
409 } 426 }
410 427
411 region = region->next; 428 region = region->next;
412 } 429 }
413 430
414 return(0); 431 return 0;
415} 432}
416 433
417int setup_iomem(void) 434int setup_iomem(void)
@@ -435,18 +452,7 @@ int setup_iomem(void)
435 region = region->next; 452 region = region->next;
436 } 453 }
437 454
438 return(0); 455 return 0;
439} 456}
440 457
441__initcall(setup_iomem); 458__initcall(setup_iomem);
442
443/*
444 * Overrides for Emacs so that we follow Linus's tabbing style.
445 * Emacs will notice this stuff at the end of the file and automatically
446 * adjust the settings for this buffer only. This must remain at the end
447 * of the file.
448 * ---------------------------------------------------------------------------
449 * Local variables:
450 * c-file-style: "linux"
451 * End:
452 */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 9a77fb3c269d..627742d89434 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -18,6 +18,7 @@
18#include "kern_util.h" 18#include "kern_util.h"
19#include "skas_ptrace.h" 19#include "skas_ptrace.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21#include "os.h"
21 22
22static inline void set_singlestepping(struct task_struct *child, int on) 23static inline void set_singlestepping(struct task_struct *child, int on)
23{ 24{
@@ -241,6 +242,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
241 break; 242 break;
242 } 243 }
243#endif 244#endif
245#ifdef PTRACE_ARCH_PRCTL
246 case PTRACE_ARCH_PRCTL:
247 /* XXX Calls ptrace on the host - needs some SMP thinking */
248 ret = arch_prctl_skas(child, data, (void *) addr);
249 break;
250#endif
244 default: 251 default:
245 ret = ptrace_request(child, request, addr, data); 252 ret = ptrace_request(child, request, addr, data);
246 break; 253 break;
diff --git a/arch/um/kernel/resource.c b/arch/um/kernel/resource.c
deleted file mode 100644
index 32188e12e8af..000000000000
--- a/arch/um/kernel/resource.c
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/pci.h"
7
8unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
9 unsigned long start, unsigned long size)
10{
11 return start;
12}
13
14/*
15 * Overrides for Emacs so that we follow Linus's tabbing style.
16 * Emacs will notice this stuff at the end of the file and automatically
17 * adjust the settings for this buffer only. This must remain at the end
18 * of the file.
19 * ---------------------------------------------------------------------------
20 * Local variables:
21 * c-file-style: "linux"
22 * End:
23 */
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 2b0ab438301c..89f9866a1354 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -23,7 +23,7 @@ static irqreturn_t sigio_interrupt(int irq, void *data)
23 23
24 os_read_file(sigio_irq_fd, &c, sizeof(c)); 24 os_read_file(sigio_irq_fd, &c, sizeof(c));
25 reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); 25 reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
26 return(IRQ_HANDLED); 26 return IRQ_HANDLED;
27} 27}
28 28
29int write_sigio_irq(int fd) 29int write_sigio_irq(int fd)
@@ -36,12 +36,13 @@ int write_sigio_irq(int fd)
36 if(err){ 36 if(err){
37 printk("write_sigio_irq : um_request_irq failed, err = %d\n", 37 printk("write_sigio_irq : um_request_irq failed, err = %d\n",
38 err); 38 err);
39 return(-1); 39 return -1;
40 } 40 }
41 sigio_irq_fd = fd; 41 sigio_irq_fd = fd;
42 return(0); 42 return 0;
43} 43}
44 44
45/* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
45static DEFINE_SPINLOCK(sigio_spinlock); 46static DEFINE_SPINLOCK(sigio_spinlock);
46 47
47void sigio_lock(void) 48void sigio_lock(void)
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 0d2cce621134..7c18dfcd7d8e 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -14,13 +14,9 @@ unsigned long set_task_sizes_skas(unsigned long *task_size_out)
14 unsigned long host_task_size = ROUND_4M((unsigned long) 14 unsigned long host_task_size = ROUND_4M((unsigned long)
15 &host_task_size); 15 &host_task_size);
16 16
17#ifdef CONFIG_HOST_TASK_SIZE
18 *host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE);
19 *task_size_out = CONFIG_HOST_TASK_SIZE;
20#else
21 if (!skas_needs_stub) 17 if (!skas_needs_stub)
22 *task_size_out = host_task_size; 18 *task_size_out = host_task_size;
23 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; 19 else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
24#endif 20
25 return host_task_size; 21 return host_task_size;
26} 22}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index f5ed8624648b..2828c5283227 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -149,22 +149,6 @@ long sys_olduname(struct oldold_utsname __user * name)
149 return error; 149 return error;
150} 150}
151 151
152DEFINE_SPINLOCK(syscall_lock);
153
154static int syscall_index = 0;
155
156int next_syscall_index(int limit)
157{
158 int ret;
159
160 spin_lock(&syscall_lock);
161 ret = syscall_index;
162 if(++syscall_index == limit)
163 syscall_index = 0;
164 spin_unlock(&syscall_lock);
165 return(ret);
166}
167
168int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 152int kernel_execve(const char *filename, char *const argv[], char *const envp[])
169{ 153{
170 mm_segment_t fs; 154 mm_segment_t fs;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 239c98054dec..f9e02b31a97a 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -50,7 +50,7 @@ void dump_stack(void)
50EXPORT_SYMBOL(dump_stack); 50EXPORT_SYMBOL(dump_stack);
51 51
52/*Stolen from arch/i386/kernel/traps.c */ 52/*Stolen from arch/i386/kernel/traps.c */
53static int kstack_depth_to_print = 24; 53static const int kstack_depth_to_print = 24;
54 54
55/* This recently started being used in arch-independent code too, as in 55/* This recently started being used in arch-independent code too, as in
56 * kernel/sched.c.*/ 56 * kernel/sched.c.*/
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 2e354b3ca060..b1f8b0752419 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -35,31 +35,31 @@ 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
38static unsigned long long prev_nsecs; 38static unsigned long long prev_nsecs[NR_CPUS];
39#ifdef CONFIG_UML_REAL_TIME_CLOCK 39#ifdef CONFIG_UML_REAL_TIME_CLOCK
40static long long delta; /* Deviation per interval */ 40static long long delta[NR_CPUS]; /* Deviation per interval */
41#endif 41#endif
42 42
43void timer_irq(union uml_pt_regs *regs) 43void timer_irq(union uml_pt_regs *regs)
44{ 44{
45 unsigned long long ticks = 0; 45 unsigned long long ticks = 0;
46
47#ifdef CONFIG_UML_REAL_TIME_CLOCK 46#ifdef CONFIG_UML_REAL_TIME_CLOCK
48 if(prev_nsecs){ 47 int c = cpu();
48 if(prev_nsecs[c]){
49 /* We've had 1 tick */ 49 /* We've had 1 tick */
50 unsigned long long nsecs = os_nsecs(); 50 unsigned long long nsecs = os_nsecs();
51 51
52 delta += nsecs - prev_nsecs; 52 delta[c] += nsecs - prev_nsecs[c];
53 prev_nsecs = nsecs; 53 prev_nsecs[c] = nsecs;
54 54
55 /* Protect against the host clock being set backwards */ 55 /* Protect against the host clock being set backwards */
56 if(delta < 0) 56 if(delta[c] < 0)
57 delta = 0; 57 delta[c] = 0;
58 58
59 ticks += (delta * HZ) / BILLION; 59 ticks += (delta[c] * HZ) / BILLION;
60 delta -= (ticks * BILLION) / HZ; 60 delta[c] -= (ticks * BILLION) / HZ;
61 } 61 }
62 else prev_nsecs = os_nsecs(); 62 else prev_nsecs[c] = os_nsecs();
63#else 63#else
64 ticks = 1; 64 ticks = 1;
65#endif 65#endif
@@ -69,8 +69,8 @@ void timer_irq(union uml_pt_regs *regs)
69 } 69 }
70} 70}
71 71
72/* Protects local_offset */
72static DEFINE_SPINLOCK(timer_spinlock); 73static DEFINE_SPINLOCK(timer_spinlock);
73
74static unsigned long long local_offset = 0; 74static unsigned long long local_offset = 0;
75 75
76static inline unsigned long long get_time(void) 76static inline unsigned long long get_time(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index b5f124a2f6ae..26f15c458574 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -128,7 +128,18 @@ out_of_memory:
128 goto out; 128 goto out;
129} 129}
130 130
131void segv_handler(int sig, union uml_pt_regs *regs) 131static void bad_segv(struct faultinfo fi, unsigned long ip)
132{
133 struct siginfo si;
134
135 si.si_signo = SIGSEGV;
136 si.si_code = SEGV_ACCERR;
137 si.si_addr = (void __user *) FAULT_ADDRESS(fi);
138 current->thread.arch.faultinfo = fi;
139 force_sig_info(SIGSEGV, &si, current);
140}
141
142static void segv_handler(int sig, union uml_pt_regs *regs)
132{ 143{
133 struct faultinfo * fi = UPT_FAULTINFO(regs); 144 struct faultinfo * fi = UPT_FAULTINFO(regs);
134 145
@@ -205,17 +216,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
205 return(0); 216 return(0);
206} 217}
207 218
208void bad_segv(struct faultinfo fi, unsigned long ip)
209{
210 struct siginfo si;
211
212 si.si_signo = SIGSEGV;
213 si.si_code = SEGV_ACCERR;
214 si.si_addr = (void __user *) FAULT_ADDRESS(fi);
215 current->thread.arch.faultinfo = fi;
216 force_sig_info(SIGSEGV, &si, current);
217}
218
219void relay_signal(int sig, union uml_pt_regs *regs) 219void relay_signal(int sig, union uml_pt_regs *regs)
220{ 220{
221 if(arch_handle_signal(sig, regs)) 221 if(arch_handle_signal(sig, regs))
@@ -232,14 +232,14 @@ void relay_signal(int sig, union uml_pt_regs *regs)
232 force_sig(sig, current); 232 force_sig(sig, current);
233} 233}
234 234
235void bus_handler(int sig, union uml_pt_regs *regs) 235static void bus_handler(int sig, union uml_pt_regs *regs)
236{ 236{
237 if(current->thread.fault_catcher != NULL) 237 if(current->thread.fault_catcher != NULL)
238 do_longjmp(current->thread.fault_catcher, 1); 238 do_longjmp(current->thread.fault_catcher, 1);
239 else relay_signal(sig, regs); 239 else relay_signal(sig, regs);
240} 240}
241 241
242void winch(int sig, union uml_pt_regs *regs) 242static void winch(int sig, union uml_pt_regs *regs)
243{ 243{
244 do_IRQ(WINCH_IRQ, regs); 244 do_IRQ(WINCH_IRQ, regs);
245} 245}
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 786e4edd86c5..8eba8f7dca68 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -139,7 +139,7 @@ static void config_gdb_cb(void *arg)
139 init_proxy(debugger_pid, 0, 0); 139 init_proxy(debugger_pid, 0, 0);
140} 140}
141 141
142int gdb_config(char *str) 142int gdb_config(char *str, char **error_out)
143{ 143{
144 struct gdb_data data; 144 struct gdb_data data;
145 145
@@ -154,7 +154,7 @@ void remove_gdb_cb(void *unused)
154 exit_debugger_cb(NULL); 154 exit_debugger_cb(NULL);
155} 155}
156 156
157int gdb_remove(int unused) 157int gdb_remove(int unused, char **error_out)
158{ 158{
159 initial_thread_cb(remove_gdb_cb, NULL); 159 initial_thread_cb(remove_gdb_cb, NULL);
160 return 0; 160 return 0;
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 68e1bf63cd0a..03b06bc00771 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -8,10 +8,11 @@
8 8
9#ifdef CONFIG_MCONSOLE 9#ifdef CONFIG_MCONSOLE
10 10
11extern int gdb_config(char *str); 11extern int gdb_config(char *str, char **error_out);
12extern int gdb_remove(int n); 12extern int gdb_remove(int n, char **error_out);
13 13
14static struct mc_device gdb_mc = { 14static struct mc_device gdb_mc = {
15 .list = INIT_LIST_HEAD(gdb_mc.list),
15 .name = "gdb", 16 .name = "gdb",
16 .config = gdb_config, 17 .config = gdb_config,
17 .remove = gdb_remove, 18 .remove = gdb_remove,
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 66f43c906821..89c6dba731f8 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -30,7 +30,6 @@
30#include "kern.h" 30#include "kern.h"
31#include "mem_user.h" 31#include "mem_user.h"
32#include "mem.h" 32#include "mem.h"
33#include "umid.h"
34#include "initrd.h" 33#include "initrd.h"
35#include "init.h" 34#include "init.h"
36#include "os.h" 35#include "os.h"
@@ -44,9 +43,9 @@
44#define DEFAULT_COMMAND_LINE "root=98:0" 43#define DEFAULT_COMMAND_LINE "root=98:0"
45 44
46/* Changed in linux_main and setup_arch, which run before SMP is started */ 45/* Changed in linux_main and setup_arch, which run before SMP is started */
47static char command_line[COMMAND_LINE_SIZE] = { 0 }; 46static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
48 47
49static void add_arg(char *arg) 48static void __init add_arg(char *arg)
50{ 49{
51 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 50 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
52 printf("add_arg: Too many command line arguments!\n"); 51 printf("add_arg: Too many command line arguments!\n");
@@ -331,7 +330,7 @@ EXPORT_SYMBOL(end_iomem);
331 330
332extern char __binary_start; 331extern char __binary_start;
333 332
334int linux_main(int argc, char **argv) 333int __init linux_main(int argc, char **argv)
335{ 334{
336 unsigned long avail, diff; 335 unsigned long avail, diff;
337 unsigned long virtmem_size, max_physmem; 336 unsigned long virtmem_size, max_physmem;
@@ -482,7 +481,7 @@ void __init setup_arch(char **cmdline_p)
482 atomic_notifier_chain_register(&panic_notifier_list, 481 atomic_notifier_chain_register(&panic_notifier_list,
483 &panic_exit_notifier); 482 &panic_exit_notifier);
484 paging_init(); 483 paging_init();
485 strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); 484 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
486 *cmdline_p = command_line; 485 *cmdline_p = command_line;
487 setup_hostinfo(); 486 setup_hostinfo();
488} 487}
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 4eaee823bfd2..039e16efcd55 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -16,8 +16,10 @@ static int __init set_umid_arg(char *name, int *add)
16{ 16{
17 int err; 17 int err;
18 18
19 if(umid_inited) 19 if(umid_inited){
20 printf("umid already set\n");
20 return 0; 21 return 0;
22 }
21 23
22 *add = 0; 24 *add = 0;
23 err = set_umid(name); 25 err = set_umid(name);
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index f897140cc4ae..6ff12743a0bd 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -24,9 +24,6 @@ struct aio_thread_req {
24 struct aio_context *aio; 24 struct aio_context *aio;
25}; 25};
26 26
27static int aio_req_fd_r = -1;
28static int aio_req_fd_w = -1;
29
30#if defined(HAVE_AIO_ABI) 27#if defined(HAVE_AIO_ABI)
31#include <linux/aio_abi.h> 28#include <linux/aio_abi.h>
32 29
@@ -111,6 +108,7 @@ static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
111 return err; 108 return err;
112} 109}
113 110
111/* Initialized in an initcall and unchanged thereafter */
114static aio_context_t ctx = 0; 112static aio_context_t ctx = 0;
115 113
116static int aio_thread(void *arg) 114static int aio_thread(void *arg)
@@ -137,7 +135,7 @@ static int aio_thread(void *arg)
137 err = os_write_file(reply_fd, &reply, sizeof(reply)); 135 err = os_write_file(reply_fd, &reply, sizeof(reply));
138 if(err != sizeof(reply)) 136 if(err != sizeof(reply))
139 printk("aio_thread - write failed, fd = %d, " 137 printk("aio_thread - write failed, fd = %d, "
140 "err = %d\n", aio_req_fd_r, -err); 138 "err = %d\n", reply_fd, -err);
141 } 139 }
142 } 140 }
143 return 0; 141 return 0;
@@ -182,6 +180,11 @@ out:
182 return err; 180 return err;
183} 181}
184 182
183/* These are initialized in initcalls and not changed */
184static int aio_req_fd_r = -1;
185static int aio_req_fd_w = -1;
186static int aio_pid = -1;
187
185static int not_aio_thread(void *arg) 188static int not_aio_thread(void *arg)
186{ 189{
187 struct aio_thread_req req; 190 struct aio_thread_req req;
@@ -208,14 +211,12 @@ static int not_aio_thread(void *arg)
208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); 211 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
209 if(err != sizeof(reply)) 212 if(err != sizeof(reply))
210 printk("not_aio_thread - write failed, fd = %d, " 213 printk("not_aio_thread - write failed, fd = %d, "
211 "err = %d\n", aio_req_fd_r, -err); 214 "err = %d\n", req.aio->reply_fd, -err);
212 } 215 }
213 216
214 return 0; 217 return 0;
215} 218}
216 219
217static int aio_pid = -1;
218
219static int init_aio_24(void) 220static int init_aio_24(void)
220{ 221{
221 unsigned long stack; 222 unsigned long stack;
@@ -308,6 +309,7 @@ static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
308} 309}
309#endif 310#endif
310 311
312/* Initialized in an initcall and unchanged thereafter */
311static int aio_24 = DEFAULT_24_AIO; 313static int aio_24 = DEFAULT_24_AIO;
312 314
313static int __init set_aio_24(char *name, int *add) 315static int __init set_aio_24(char *name, int *add)
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 5a99dd3fbed0..3a8d7e3aae0a 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -21,12 +21,11 @@ typedef Elf32_auxv_t elf_auxv_t;
21typedef Elf64_auxv_t elf_auxv_t; 21typedef Elf64_auxv_t elf_auxv_t;
22#endif 22#endif
23 23
24/* These are initialized very early in boot and never changed */
24char * elf_aux_platform; 25char * elf_aux_platform;
25long elf_aux_hwcap; 26long elf_aux_hwcap;
26
27unsigned long vsyscall_ehdr; 27unsigned long vsyscall_ehdr;
28unsigned long vsyscall_end; 28unsigned long vsyscall_end;
29
30unsigned long __kernel_vsyscall; 29unsigned long __kernel_vsyscall;
31 30
32__init void scan_elf_aux( char **envp) 31__init void scan_elf_aux( char **envp)
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 189fa677085a..371b4335f46d 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -162,25 +162,6 @@ int os_set_owner(int fd, int pid)
162 return 0; 162 return 0;
163} 163}
164 164
165/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
166int os_sigio_async(int master, int slave)
167{
168 int flags;
169
170 flags = fcntl(master, F_GETFL);
171 if(flags < 0)
172 return -errno;
173
174 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
175 (fcntl(master, F_SETOWN, os_getpid()) < 0))
176 return -errno;
177
178 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
179 return -errno;
180
181 return(0);
182}
183
184int os_mode_fd(int fd, int mode) 165int os_mode_fd(int fd, int mode)
185{ 166{
186 int err; 167 int err;
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index d46b818c1311..d1b61d474e0a 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -20,6 +20,10 @@
20#include "os.h" 20#include "os.h"
21#include "um_malloc.h" 21#include "um_malloc.h"
22 22
23/*
24 * Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd
25 * and os_free_irq_by_cb, which are called under irq_lock.
26 */
23static struct pollfd *pollfds = NULL; 27static struct pollfd *pollfds = NULL;
24static int pollfds_num = 0; 28static int pollfds_num = 0;
25static int pollfds_size = 0; 29static int pollfds_size = 0;
@@ -58,7 +62,7 @@ int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
58 if (pollfds_num == pollfds_size) { 62 if (pollfds_num == pollfds_size) {
59 if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) { 63 if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) {
60 /* return min size needed for new pollfds area */ 64 /* return min size needed for new pollfds area */
61 return((pollfds_size + 1) * sizeof(pollfds[0])); 65 return (pollfds_size + 1) * sizeof(pollfds[0]);
62 } 66 }
63 67
64 if (pollfds != NULL) { 68 if (pollfds != NULL) {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 4203681e508d..f1ea169db85e 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -20,7 +20,13 @@
20 20
21#include <sys/param.h> 21#include <sys/param.h>
22 22
23/* Modified by which_tmpdir, which is called during early boot */
23static char *default_tmpdir = "/tmp"; 24static char *default_tmpdir = "/tmp";
25
26/*
27 * Modified when creating the physical memory file and when checking
28 * the tmp filesystem for usability, both happening during early boot.
29 */
24static char *tempdir = NULL; 30static char *tempdir = NULL;
25 31
26static void __init find_tempdir(void) 32static void __init find_tempdir(void)
@@ -29,7 +35,8 @@ static void __init find_tempdir(void)
29 int i; 35 int i;
30 char *dir = NULL; 36 char *dir = NULL;
31 37
32 if(tempdir != NULL) return; /* We've already been called */ 38 if(tempdir != NULL) /* We've already been called */
39 return;
33 for(i = 0; dirs[i]; i++){ 40 for(i = 0; dirs[i]; i++){
34 dir = getenv(dirs[i]); 41 dir = getenv(dirs[i]);
35 if((dir != NULL) && (*dir != '\0')) 42 if((dir != NULL) && (*dir != '\0'))
@@ -83,6 +90,7 @@ static int next(int fd, char *buf, int size, char c)
83 return 1; 90 return 1;
84} 91}
85 92
93/* which_tmpdir is called only during early boot */
86static int checked_tmpdir = 0; 94static int checked_tmpdir = 0;
87 95
88/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner 96/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
@@ -186,7 +194,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
186 } else { 194 } else {
187 free(tempname); 195 free(tempname);
188 } 196 }
189 return(fd); 197 return fd;
190out: 198out:
191 free(tempname); 199 free(tempname);
192 return -1; 200 return -1;
@@ -231,7 +239,7 @@ int create_tmp_file(unsigned long long len)
231 exit(1); 239 exit(1);
232 } 240 }
233 241
234 return(fd); 242 return fd;
235} 243}
236 244
237int create_mem_file(unsigned long long len) 245int create_mem_file(unsigned long long len)
@@ -245,7 +253,7 @@ int create_mem_file(unsigned long long len)
245 errno = -err; 253 errno = -err;
246 perror("exec_close"); 254 perror("exec_close");
247 } 255 }
248 return(fd); 256 return fd;
249} 257}
250 258
251 259
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7fe92680c7dd..5178eba9afa5 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -54,7 +54,7 @@ static int ptrace_child(void *arg)
54 perror("ptrace"); 54 perror("ptrace");
55 os_kill_process(pid, 0); 55 os_kill_process(pid, 0);
56 } 56 }
57 os_stop_process(pid); 57 kill(pid, SIGSTOP);
58 58
59 /*This syscall will be intercepted by the parent. Don't call more than 59 /*This syscall will be intercepted by the parent. Don't call more than
60 * once, please.*/ 60 * once, please.*/
@@ -73,6 +73,34 @@ static int ptrace_child(void *arg)
73 _exit(ret); 73 _exit(ret);
74} 74}
75 75
76static void fatal_perror(char *str)
77{
78 perror(str);
79 exit(1);
80}
81
82static void fatal(char *fmt, ...)
83{
84 va_list list;
85
86 va_start(list, fmt);
87 vprintf(fmt, list);
88 va_end(list);
89 fflush(stdout);
90
91 exit(1);
92}
93
94static void non_fatal(char *fmt, ...)
95{
96 va_list list;
97
98 va_start(list, fmt);
99 vprintf(fmt, list);
100 va_end(list);
101 fflush(stdout);
102}
103
76static int start_ptraced_child(void **stack_out) 104static int start_ptraced_child(void **stack_out)
77{ 105{
78 void *stack; 106 void *stack;
@@ -82,20 +110,20 @@ static int start_ptraced_child(void **stack_out)
82 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, 110 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
83 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 111 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
84 if(stack == MAP_FAILED) 112 if(stack == MAP_FAILED)
85 panic("check_ptrace : mmap failed, errno = %d", errno); 113 fatal_perror("check_ptrace : mmap failed");
86 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); 114 sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
87 pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); 115 pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
88 if(pid < 0) 116 if(pid < 0)
89 panic("start_ptraced_child : clone failed, errno = %d", errno); 117 fatal_perror("start_ptraced_child : clone failed");
90 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 118 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
91 if(n < 0) 119 if(n < 0)
92 panic("check_ptrace : clone failed, errno = %d", errno); 120 fatal_perror("check_ptrace : clone failed");
93 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) 121 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
94 panic("check_ptrace : expected SIGSTOP, got status = %d", 122 fatal("check_ptrace : expected SIGSTOP, got status = %d",
95 status); 123 status);
96 124
97 *stack_out = stack; 125 *stack_out = stack;
98 return(pid); 126 return pid;
99} 127}
100 128
101/* When testing for SYSEMU support, if it is one of the broken versions, we 129/* When testing for SYSEMU support, if it is one of the broken versions, we
@@ -105,34 +133,34 @@ static int start_ptraced_child(void **stack_out)
105 * must work anyway! 133 * must work anyway!
106 */ 134 */
107static int stop_ptraced_child(int pid, void *stack, int exitcode, 135static int stop_ptraced_child(int pid, void *stack, int exitcode,
108 int mustpanic) 136 int mustexit)
109{ 137{
110 int status, n, ret = 0; 138 int status, n, ret = 0;
111 139
112 if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) 140 if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
113 panic("check_ptrace : ptrace failed, errno = %d", errno); 141 fatal_perror("stop_ptraced_child : ptrace failed");
114 CATCH_EINTR(n = waitpid(pid, &status, 0)); 142 CATCH_EINTR(n = waitpid(pid, &status, 0));
115 if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { 143 if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
116 int exit_with = WEXITSTATUS(status); 144 int exit_with = WEXITSTATUS(status);
117 if (exit_with == 2) 145 if (exit_with == 2)
118 printf("check_ptrace : child exited with status 2. " 146 non_fatal("check_ptrace : child exited with status 2. "
119 "Serious trouble happening! Try updating your " 147 "Serious trouble happening! Try updating "
120 "host skas patch!\nDisabling SYSEMU support."); 148 "your host skas patch!\nDisabling SYSEMU "
121 printf("check_ptrace : child exited with exitcode %d, while " 149 "support.");
122 "expecting %d; status 0x%x", exit_with, 150 non_fatal("check_ptrace : child exited with exitcode %d, while "
123 exitcode, status); 151 "expecting %d; status 0x%x\n", exit_with,
124 if (mustpanic) 152 exitcode, status);
125 panic("\n"); 153 if (mustexit)
126 else 154 exit(1);
127 printf("\n");
128 ret = -1; 155 ret = -1;
129 } 156 }
130 157
131 if(munmap(stack, PAGE_SIZE) < 0) 158 if(munmap(stack, PAGE_SIZE) < 0)
132 panic("check_ptrace : munmap failed, errno = %d", errno); 159 fatal_perror("check_ptrace : munmap failed");
133 return ret; 160 return ret;
134} 161}
135 162
163/* Changed only during early boot */
136int ptrace_faultinfo = 1; 164int ptrace_faultinfo = 1;
137int ptrace_ldt = 1; 165int ptrace_ldt = 1;
138int proc_mm = 1; 166int proc_mm = 1;
@@ -160,6 +188,7 @@ __uml_setup("mode=skas0", mode_skas0_cmd_param,
160 " specify mode=tt. Note that this was recently added - on \n" 188 " specify mode=tt. Note that this was recently added - on \n"
161 " older kernels you must use simply \"skas0\".\n\n"); 189 " older kernels you must use simply \"skas0\".\n\n");
162 190
191/* Changed only during early boot */
163static int force_sysemu_disabled = 0; 192static int force_sysemu_disabled = 0;
164 193
165static int __init nosysemu_cmd_param(char *str, int* add) 194static int __init nosysemu_cmd_param(char *str, int* add)
@@ -180,9 +209,9 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
180static void __init check_sysemu(void) 209static void __init check_sysemu(void)
181{ 210{
182 void *stack; 211 void *stack;
183 int pid, n, status, count=0; 212 int pid, n, status, count=0;
184 213
185 printf("Checking syscall emulation patch for ptrace..."); 214 non_fatal("Checking syscall emulation patch for ptrace...");
186 sysemu_supported = 0; 215 sysemu_supported = 0;
187 pid = start_ptraced_child(&stack); 216 pid = start_ptraced_child(&stack);
188 217
@@ -191,31 +220,30 @@ static void __init check_sysemu(void)
191 220
192 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 221 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
193 if (n < 0) 222 if (n < 0)
194 panic("check_sysemu : wait failed, errno = %d", errno); 223 fatal_perror("check_sysemu : wait failed");
195 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) 224 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
196 panic("check_sysemu : expected SIGTRAP, " 225 fatal("check_sysemu : expected SIGTRAP, got status = %d",
197 "got status = %d", status); 226 status);
198 227
199 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, 228 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
200 os_getpid()); 229 os_getpid());
201 if(n < 0) 230 if(n < 0)
202 panic("check_sysemu : failed to modify system " 231 fatal_perror("check_sysemu : failed to modify system call "
203 "call return, errno = %d", errno); 232 "return");
204 233
205 if (stop_ptraced_child(pid, stack, 0, 0) < 0) 234 if (stop_ptraced_child(pid, stack, 0, 0) < 0)
206 goto fail_stopped; 235 goto fail_stopped;
207 236
208 sysemu_supported = 1; 237 sysemu_supported = 1;
209 printf("OK\n"); 238 non_fatal("OK\n");
210 set_using_sysemu(!force_sysemu_disabled); 239 set_using_sysemu(!force_sysemu_disabled);
211 240
212 printf("Checking advanced syscall emulation patch for ptrace..."); 241 non_fatal("Checking advanced syscall emulation patch for ptrace...");
213 pid = start_ptraced_child(&stack); 242 pid = start_ptraced_child(&stack);
214 243
215 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, 244 if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
216 (void *) PTRACE_O_TRACESYSGOOD) < 0) 245 (void *) PTRACE_O_TRACESYSGOOD) < 0))
217 panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", 246 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
218 errno);
219 247
220 while(1){ 248 while(1){
221 count++; 249 count++;
@@ -223,29 +251,30 @@ static void __init check_sysemu(void)
223 goto fail; 251 goto fail;
224 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 252 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
225 if(n < 0) 253 if(n < 0)
226 panic("check_ptrace : wait failed, errno = %d", errno); 254 fatal_perror("check_ptrace : wait failed");
255
227 if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){ 256 if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
228 if (!count) 257 if (!count)
229 panic("check_ptrace : SYSEMU_SINGLESTEP " 258 fatal("check_ptrace : SYSEMU_SINGLESTEP "
230 "doesn't singlestep"); 259 "doesn't singlestep");
231 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, 260 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
232 os_getpid()); 261 os_getpid());
233 if(n < 0) 262 if(n < 0)
234 panic("check_sysemu : failed to modify system " 263 fatal_perror("check_sysemu : failed to modify "
235 "call return, errno = %d", errno); 264 "system call return");
236 break; 265 break;
237 } 266 }
238 else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) 267 else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
239 count++; 268 count++;
240 else 269 else
241 panic("check_ptrace : expected SIGTRAP or " 270 fatal("check_ptrace : expected SIGTRAP or "
242 "(SIGTRAP|0x80), got status = %d", status); 271 "(SIGTRAP | 0x80), got status = %d", status);
243 } 272 }
244 if (stop_ptraced_child(pid, stack, 0, 0) < 0) 273 if (stop_ptraced_child(pid, stack, 0, 0) < 0)
245 goto fail_stopped; 274 goto fail_stopped;
246 275
247 sysemu_supported = 2; 276 sysemu_supported = 2;
248 printf("OK\n"); 277 non_fatal("OK\n");
249 278
250 if ( !force_sysemu_disabled ) 279 if ( !force_sysemu_disabled )
251 set_using_sysemu(sysemu_supported); 280 set_using_sysemu(sysemu_supported);
@@ -254,7 +283,7 @@ static void __init check_sysemu(void)
254fail: 283fail:
255 stop_ptraced_child(pid, stack, 1, 0); 284 stop_ptraced_child(pid, stack, 1, 0);
256fail_stopped: 285fail_stopped:
257 printf("missing\n"); 286 non_fatal("missing\n");
258} 287}
259 288
260static void __init check_ptrace(void) 289static void __init check_ptrace(void)
@@ -262,22 +291,25 @@ static void __init check_ptrace(void)
262 void *stack; 291 void *stack;
263 int pid, syscall, n, status; 292 int pid, syscall, n, status;
264 293
265 printf("Checking that ptrace can change system call numbers..."); 294 non_fatal("Checking that ptrace can change system call numbers...");
266 pid = start_ptraced_child(&stack); 295 pid = start_ptraced_child(&stack);
267 296
268 if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) 297 if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
269 panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno); 298 (void *) PTRACE_O_TRACESYSGOOD) < 0))
299 fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
270 300
271 while(1){ 301 while(1){
272 if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) 302 if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
273 panic("check_ptrace : ptrace failed, errno = %d", 303 fatal_perror("check_ptrace : ptrace failed");
274 errno); 304
275 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 305 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
276 if(n < 0) 306 if(n < 0)
277 panic("check_ptrace : wait failed, errno = %d", errno); 307 fatal_perror("check_ptrace : wait failed");
278 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80))) 308
279 panic("check_ptrace : expected (SIGTRAP|0x80), " 309 if(!WIFSTOPPED(status) ||
280 "got status = %d", status); 310 (WSTOPSIG(status) != (SIGTRAP | 0x80)))
311 fatal("check_ptrace : expected (SIGTRAP|0x80), "
312 "got status = %d", status);
281 313
282 syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 314 syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
283 0); 315 0);
@@ -285,13 +317,13 @@ static void __init check_ptrace(void)
285 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, 317 n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
286 __NR_getppid); 318 __NR_getppid);
287 if(n < 0) 319 if(n < 0)
288 panic("check_ptrace : failed to modify system " 320 fatal_perror("check_ptrace : failed to modify "
289 "call, errno = %d", errno); 321 "system call");
290 break; 322 break;
291 } 323 }
292 } 324 }
293 stop_ptraced_child(pid, stack, 0, 1); 325 stop_ptraced_child(pid, stack, 0, 1);
294 printf("OK\n"); 326 non_fatal("OK\n");
295 check_sysemu(); 327 check_sysemu();
296} 328}
297 329
@@ -350,22 +382,22 @@ static inline void check_skas3_ptrace_faultinfo(void)
350 void *stack; 382 void *stack;
351 int pid, n; 383 int pid, n;
352 384
353 printf(" - PTRACE_FAULTINFO..."); 385 non_fatal(" - PTRACE_FAULTINFO...");
354 pid = start_ptraced_child(&stack); 386 pid = start_ptraced_child(&stack);
355 387
356 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); 388 n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
357 if (n < 0) { 389 if (n < 0) {
358 ptrace_faultinfo = 0; 390 ptrace_faultinfo = 0;
359 if(errno == EIO) 391 if(errno == EIO)
360 printf("not found\n"); 392 non_fatal("not found\n");
361 else 393 else
362 perror("not found"); 394 perror("not found");
363 } 395 }
364 else { 396 else {
365 if (!ptrace_faultinfo) 397 if (!ptrace_faultinfo)
366 printf("found but disabled on command line\n"); 398 non_fatal("found but disabled on command line\n");
367 else 399 else
368 printf("found\n"); 400 non_fatal("found\n");
369 } 401 }
370 402
371 init_registers(pid); 403 init_registers(pid);
@@ -383,13 +415,13 @@ static inline void check_skas3_ptrace_ldt(void)
383 .ptr = ldtbuf, 415 .ptr = ldtbuf,
384 .bytecount = sizeof(ldtbuf)}; 416 .bytecount = sizeof(ldtbuf)};
385 417
386 printf(" - PTRACE_LDT..."); 418 non_fatal(" - PTRACE_LDT...");
387 pid = start_ptraced_child(&stack); 419 pid = start_ptraced_child(&stack);
388 420
389 n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op); 421 n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
390 if (n < 0) { 422 if (n < 0) {
391 if(errno == EIO) 423 if(errno == EIO)
392 printf("not found\n"); 424 non_fatal("not found\n");
393 else { 425 else {
394 perror("not found"); 426 perror("not found");
395 } 427 }
@@ -397,9 +429,9 @@ static inline void check_skas3_ptrace_ldt(void)
397 } 429 }
398 else { 430 else {
399 if(ptrace_ldt) 431 if(ptrace_ldt)
400 printf("found\n"); 432 non_fatal("found\n");
401 else 433 else
402 printf("found, but use is disabled\n"); 434 non_fatal("found, but use is disabled\n");
403 } 435 }
404 436
405 stop_ptraced_child(pid, stack, 1, 1); 437 stop_ptraced_child(pid, stack, 1, 1);
@@ -414,22 +446,22 @@ static inline void check_skas3_ptrace_ldt(void)
414 446
415static inline void check_skas3_proc_mm(void) 447static inline void check_skas3_proc_mm(void)
416{ 448{
417 printf(" - /proc/mm..."); 449 non_fatal(" - /proc/mm...");
418 if (os_access("/proc/mm", OS_ACC_W_OK) < 0) { 450 if (access("/proc/mm", W_OK) < 0) {
419 proc_mm = 0; 451 proc_mm = 0;
420 printf("not found\n"); 452 perror("not found");
421 } 453 }
422 else { 454 else {
423 if (!proc_mm) 455 if (!proc_mm)
424 printf("found but disabled on command line\n"); 456 non_fatal("found but disabled on command line\n");
425 else 457 else
426 printf("found\n"); 458 non_fatal("found\n");
427 } 459 }
428} 460}
429 461
430int can_do_skas(void) 462int can_do_skas(void)
431{ 463{
432 printf("Checking for the skas3 patch in the host:\n"); 464 non_fatal("Checking for the skas3 patch in the host:\n");
433 465
434 check_skas3_proc_mm(); 466 check_skas3_proc_mm();
435 check_skas3_ptrace_faultinfo(); 467 check_skas3_ptrace_faultinfo();
@@ -443,16 +475,16 @@ int can_do_skas(void)
443#else 475#else
444int can_do_skas(void) 476int can_do_skas(void)
445{ 477{
446 return(0); 478 return 0;
447} 479}
448#endif 480#endif
449 481
450int __init parse_iomem(char *str, int *add) 482int __init parse_iomem(char *str, int *add)
451{ 483{
452 struct iomem_region *new; 484 struct iomem_region *new;
453 struct uml_stat buf; 485 struct stat64 buf;
454 char *file, *driver; 486 char *file, *driver;
455 int fd, err, size; 487 int fd, size;
456 488
457 driver = str; 489 driver = str;
458 file = strchr(str,','); 490 file = strchr(str,',');
@@ -462,15 +494,14 @@ int __init parse_iomem(char *str, int *add)
462 } 494 }
463 *file = '\0'; 495 *file = '\0';
464 file++; 496 file++;
465 fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); 497 fd = open(file, O_RDWR, 0);
466 if(fd < 0){ 498 if(fd < 0){
467 os_print_error(fd, "parse_iomem - Couldn't open io file"); 499 os_print_error(fd, "parse_iomem - Couldn't open io file");
468 goto out; 500 goto out;
469 } 501 }
470 502
471 err = os_stat_fd(fd, &buf); 503 if(fstat64(fd, &buf) < 0){
472 if(err < 0){ 504 perror("parse_iomem - cannot stat_fd file");
473 os_print_error(err, "parse_iomem - cannot stat_fd file");
474 goto out_close; 505 goto out_close;
475 } 506 }
476 507
@@ -480,7 +511,7 @@ int __init parse_iomem(char *str, int *add)
480 goto out_close; 511 goto out_close;
481 } 512 }
482 513
483 size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); 514 size = (buf.st_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
484 515
485 *new = ((struct iomem_region) { .next = iomem_regions, 516 *new = ((struct iomem_region) { .next = iomem_regions,
486 .driver = driver, 517 .driver = driver,
@@ -491,11 +522,11 @@ int __init parse_iomem(char *str, int *add)
491 iomem_regions = new; 522 iomem_regions = new;
492 iomem_size += new->size + UM_KERN_PAGE_SIZE; 523 iomem_size += new->size + UM_KERN_PAGE_SIZE;
493 524
494 return(0); 525 return 0;
495 out_close: 526 out_close:
496 os_close_file(fd); 527 close(fd);
497 out: 528 out:
498 return(1); 529 return 1;
499} 530}
500 531
501 532
@@ -526,6 +557,24 @@ static void openpty_cb(void *arg)
526 info->err = -errno; 557 info->err = -errno;
527} 558}
528 559
560static int async_pty(int master, int slave)
561{
562 int flags;
563
564 flags = fcntl(master, F_GETFL);
565 if(flags < 0)
566 return -errno;
567
568 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
569 (fcntl(master, F_SETOWN, os_getpid()) < 0))
570 return -errno;
571
572 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
573 return -errno;
574
575 return(0);
576}
577
529static void __init check_one_sigio(void (*proc)(int, int)) 578static void __init check_one_sigio(void (*proc)(int, int))
530{ 579{
531 struct sigaction old, new; 580 struct sigaction old, new;
@@ -551,7 +600,7 @@ static void __init check_one_sigio(void (*proc)(int, int))
551 if (err < 0) 600 if (err < 0)
552 panic("check_sigio : __raw failed, errno = %d\n", -err); 601 panic("check_sigio : __raw failed, errno = %d\n", -err);
553 602
554 err = os_sigio_async(master, slave); 603 err = async_pty(master, slave);
555 if(err < 0) 604 if(err < 0)
556 panic("tty_fds : sigio_async failed, err = %d\n", -err); 605 panic("tty_fds : sigio_async failed, err = %d\n", -err);
557 606
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 7cd0369e02b3..79cd93c8c5ed 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -34,27 +34,27 @@ void init_thread_registers(union uml_pt_regs *to)
34int save_fp_registers(int pid, unsigned long *fp_regs) 34int save_fp_registers(int pid, unsigned long *fp_regs)
35{ 35{
36 if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 36 if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
37 return(-errno); 37 return -errno;
38 return(0); 38 return 0;
39} 39}
40 40
41int restore_fp_registers(int pid, unsigned long *fp_regs) 41int restore_fp_registers(int pid, unsigned long *fp_regs)
42{ 42{
43 if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 43 if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
44 return(-errno); 44 return -errno;
45 return(0); 45 return 0;
46} 46}
47 47
48static int move_registers(int pid, int int_op, union uml_pt_regs *regs, 48static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
49 int fp_op, unsigned long *fp_regs) 49 int fp_op, unsigned long *fp_regs)
50{ 50{
51 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) 51 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
52 return(-errno); 52 return -errno;
53 53
54 if(ptrace(fp_op, pid, 0, fp_regs) < 0) 54 if(ptrace(fp_op, pid, 0, fp_regs) < 0)
55 return(-errno); 55 return -errno;
56 56
57 return(0); 57 return 0;
58} 58}
59 59
60void save_registers(int pid, union uml_pt_regs *regs) 60void save_registers(int pid, union uml_pt_regs *regs)
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index f67842a7735b..7955e061a678 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
6obj-$(CONFIG_MODE_SKAS) = registers.o signal.o 6obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o
7 7
8USER_OBJS := $(obj-y) 8USER_OBJS := $(obj-y)
9 9
diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/um/os-Linux/sys-x86_64/prctl.c
new file mode 100644
index 000000000000..9d34eddb517f
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/prctl.c
@@ -0,0 +1,12 @@
1/*
2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com})
3 * Licensed under the GPL
4 */
5
6#include <sys/ptrace.h>
7#include <linux/ptrace.h>
8
9int os_arch_prctl(int pid, int code, unsigned long *addr)
10{
11 return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
12}
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index cb8e8a263280..a2d7e0c603f7 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -27,12 +27,12 @@ static int move_registers(int pid, int int_op, int fp_op,
27 union uml_pt_regs *regs) 27 union uml_pt_regs *regs)
28{ 28{
29 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) 29 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
30 return(-errno); 30 return -errno;
31 31
32 if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0) 32 if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0)
33 return(-errno); 33 return -errno;
34 34
35 return(0); 35 return 0;
36} 36}
37 37
38void save_registers(int pid, union uml_pt_regs *regs) 38void save_registers(int pid, union uml_pt_regs *regs)
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 48092b95c8ab..b462863f7172 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -18,7 +18,7 @@
18#define UMID_LEN 64 18#define UMID_LEN 64
19 19
20/* Changed by set_umid, which is run early in boot */ 20/* Changed by set_umid, which is run early in boot */
21char umid[UMID_LEN] = { 0 }; 21static char umid[UMID_LEN] = { 0 };
22 22
23/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ 23/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
24static char *uml_dir = UML_DIR; 24static char *uml_dir = UML_DIR;
@@ -235,6 +235,7 @@ int __init set_umid(char *name)
235 return 0; 235 return 0;
236} 236}
237 237
238/* Changed in make_umid, which is called during early boot */
238static int umid_setup = 0; 239static int umid_setup = 0;
239 240
240int __init make_umid(void) 241int __init make_umid(void)
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index 147bbf05cbc2..55b66e09a98c 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -71,8 +71,6 @@ int poke_user(struct task_struct *child, long addr, long data)
71 71
72 if (addr < MAX_REG_OFFSET) 72 if (addr < MAX_REG_OFFSET)
73 return putreg(child, addr, data); 73 return putreg(child, addr, data);
74
75#if 0 /* Need x86_64 debugregs handling */
76 else if((addr >= offsetof(struct user, u_debugreg[0])) && 74 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
77 (addr <= offsetof(struct user, u_debugreg[7]))){ 75 (addr <= offsetof(struct user, u_debugreg[7]))){
78 addr -= offsetof(struct user, u_debugreg[0]); 76 addr -= offsetof(struct user, u_debugreg[0]);
@@ -81,7 +79,6 @@ int poke_user(struct task_struct *child, long addr, long data)
81 child->thread.arch.debugregs[addr] = data; 79 child->thread.arch.debugregs[addr] = data;
82 return 0; 80 return 0;
83 } 81 }
84#endif
85 return -EIO; 82 return -EIO;
86} 83}
87 84
@@ -119,14 +116,12 @@ int peek_user(struct task_struct *child, long addr, long data)
119 if(addr < MAX_REG_OFFSET){ 116 if(addr < MAX_REG_OFFSET){
120 tmp = getreg(child, addr); 117 tmp = getreg(child, addr);
121 } 118 }
122#if 0 /* Need x86_64 debugregs handling */
123 else if((addr >= offsetof(struct user, u_debugreg[0])) && 119 else if((addr >= offsetof(struct user, u_debugreg[0])) &&
124 (addr <= offsetof(struct user, u_debugreg[7]))){ 120 (addr <= offsetof(struct user, u_debugreg[7]))){
125 addr -= offsetof(struct user, u_debugreg[0]); 121 addr -= offsetof(struct user, u_debugreg[0]);
126 addr = addr >> 2; 122 addr = addr >> 2;
127 tmp = child->thread.arch.debugregs[addr]; 123 tmp = child->thread.arch.debugregs[addr];
128 } 124 }
129#endif
130 return put_user(tmp, (unsigned long *) data); 125 return put_user(tmp, (unsigned long *) data);
131} 126}
132 127
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 73ce4463f70c..01b91f9fa789 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -16,6 +16,7 @@
16#include "asm/prctl.h" /* XXX This should get the constants from libc */ 16#include "asm/prctl.h" /* XXX This should get the constants from libc */
17#include "choose-mode.h" 17#include "choose-mode.h"
18#include "kern.h" 18#include "kern.h"
19#include "os.h"
19 20
20asmlinkage long sys_uname64(struct new_utsname __user * name) 21asmlinkage long sys_uname64(struct new_utsname __user * name)
21{ 22{
@@ -58,40 +59,69 @@ static long arch_prctl_tt(int code, unsigned long addr)
58 59
59#ifdef CONFIG_MODE_SKAS 60#ifdef CONFIG_MODE_SKAS
60 61
61/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */ 62long arch_prctl_skas(struct task_struct *task, int code,
62static long arch_prctl_skas(int code, unsigned long addr) 63 unsigned long __user *addr)
63{ 64{
64 long ret = 0; 65 unsigned long *ptr = addr, tmp;
66 long ret;
67 int pid = task->mm->context.skas.id.u.pid;
65 68
69 /*
70 * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
71 * be safe), we need to call arch_prctl on the host because
72 * setting %fs may result in something else happening (like a
73 * GDT or thread.fs being set instead). So, we let the host
74 * fiddle the registers and thread struct and restore the
75 * registers afterwards.
76 *
77 * So, the saved registers are stored to the process (this
78 * needed because a stub may have been the last thing to run),
79 * arch_prctl is run on the host, then the registers are read
80 * back.
81 */
66 switch(code){ 82 switch(code){
67 case ARCH_SET_FS: 83 case ARCH_SET_FS:
68 current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
69 break;
70 case ARCH_SET_GS: 84 case ARCH_SET_GS:
71 current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; 85 restore_registers(pid, &current->thread.regs.regs);
86 break;
87 case ARCH_GET_FS:
88 case ARCH_GET_GS:
89 /*
90 * With these two, we read to a local pointer and
91 * put_user it to the userspace pointer that we were
92 * given. If addr isn't valid (because it hasn't been
93 * faulted in or is just bogus), we want put_user to
94 * fault it in (or return -EFAULT) instead of having
95 * the host return -EFAULT.
96 */
97 ptr = &tmp;
98 }
99
100 ret = os_arch_prctl(pid, code, ptr);
101 if(ret)
102 return ret;
103
104 switch(code){
105 case ARCH_SET_FS:
106 case ARCH_SET_GS:
107 save_registers(pid, &current->thread.regs.regs);
72 break; 108 break;
73 case ARCH_GET_FS: 109 case ARCH_GET_FS:
74 ret = put_user(current->thread.regs.regs.skas. 110 ret = put_user(tmp, addr);
75 regs[FS_BASE / sizeof(unsigned long)],
76 (unsigned long __user *)addr);
77 break; 111 break;
78 case ARCH_GET_GS: 112 case ARCH_GET_GS:
79 ret = put_user(current->thread.regs.regs.skas. 113 ret = put_user(tmp, addr);
80 regs[GS_BASE / sizeof(unsigned long)],
81 (unsigned long __user *)addr);
82 break; 114 break;
83 default:
84 ret = -EINVAL;
85 break;
86 } 115 }
87 116
88 return(ret); 117 return ret;
89} 118}
90#endif 119#endif
91 120
92long sys_arch_prctl(int code, unsigned long addr) 121long sys_arch_prctl(int code, unsigned long addr)
93{ 122{
94 return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr)); 123 return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
124 (unsigned long __user *) addr);
95} 125}
96 126
97long sys_clone(unsigned long clone_flags, unsigned long newsp, 127long sys_clone(unsigned long clone_flags, unsigned long newsp,
@@ -105,5 +135,14 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
105 ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid, 135 ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
106 child_tid); 136 child_tid);
107 current->thread.forking = 0; 137 current->thread.forking = 0;
108 return(ret); 138 return ret;
139}
140
141void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
142{
143 if(to->thread.arch.fs == 0)
144 return;
145
146 arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
109} 147}
148
diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c
index ce1bf1b81c43..febbc94be25f 100644
--- a/arch/um/sys-x86_64/tls.c
+++ b/arch/um/sys-x86_64/tls.c
@@ -1,14 +1,17 @@
1#include "linux/sched.h" 1#include "linux/sched.h"
2 2
3void debug_arch_force_load_TLS(void)
4{
5}
6
7void clear_flushed_tls(struct task_struct *task) 3void clear_flushed_tls(struct task_struct *task)
8{ 4{
9} 5}
10 6
11int arch_copy_tls(struct task_struct *t) 7int arch_copy_tls(struct task_struct *t)
12{ 8{
9 /*
10 * If CLONE_SETTLS is set, we need to save the thread id
11 * (which is argument 5, child_tid, of clone) so it can be set
12 * during context switches.
13 */
14 t->thread.arch.fs = t->thread.regs.regs.skas.regs[R8 / sizeof(long)];
15
13 return 0; 16 return 0;
14} 17}