aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-01-12 17:47:08 -0500
committerSteve French <sfrench@us.ibm.com>2006-01-12 17:47:08 -0500
commit94bc2be31a01a3055ec94176e595dfe208e92d3b (patch)
treeebfbe81c6718a6390bfa1b99c6d228237d818576 /arch/um
parentc32a0b689cb9cc160cfcd19735bbf50bb70c6ef4 (diff)
parent58cba4650a7a414eabd2b40cc9d8e45fcdf192d9 (diff)
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig14
-rw-r--r--arch/um/Makefile23
-rw-r--r--arch/um/drivers/chan_kern.c275
-rw-r--r--arch/um/drivers/line.c298
-rw-r--r--arch/um/drivers/mconsole_kern.c232
-rw-r--r--arch/um/drivers/mconsole_user.c12
-rw-r--r--arch/um/drivers/net_kern.c8
-rw-r--r--arch/um/drivers/ssl.c47
-rw-r--r--arch/um/drivers/stdio_console.c33
-rw-r--r--arch/um/drivers/ubd_kern.c37
-rw-r--r--arch/um/include/chan_kern.h25
-rw-r--r--arch/um/include/choose-mode.h3
-rw-r--r--arch/um/include/irq_user.h13
-rw-r--r--arch/um/include/kern.h13
-rw-r--r--arch/um/include/kern_util.h19
-rw-r--r--arch/um/include/line.h37
-rw-r--r--arch/um/include/mconsole.h8
-rw-r--r--arch/um/include/os.h33
-rw-r--r--arch/um/include/signal_user.h28
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h (renamed from arch/um/sys-i386/kernel-offsets.c)5
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h (renamed from arch/um/sys-x86_64/kernel-offsets.c)2
-rw-r--r--arch/um/include/user_util.h11
-rw-r--r--arch/um/kernel/Makefile8
-rw-r--r--arch/um/kernel/asm-offsets.c2
-rw-r--r--arch/um/kernel/irq_user.c49
-rw-r--r--arch/um/kernel/process_kern.c7
-rw-r--r--arch/um/kernel/reboot.c2
-rw-r--r--arch/um/kernel/sigio_user.c2
-rw-r--r--arch/um/kernel/signal_kern.c1
-rw-r--r--arch/um/kernel/signal_user.c157
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--arch/um/kernel/skas/include/skas.h1
-rw-r--r--arch/um/kernel/skas/process.c15
-rw-r--r--arch/um/kernel/skas/process_kern.c5
-rw-r--r--arch/um/kernel/time.c9
-rw-r--r--arch/um/kernel/trap_kern.c25
-rw-r--r--arch/um/kernel/trap_user.c98
-rw-r--r--arch/um/kernel/tt/exec_kern.c3
-rw-r--r--arch/um/kernel/tt/process_kern.c9
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c16
-rw-r--r--arch/um/kernel/um_arch.c15
-rw-r--r--arch/um/kernel/umid.c323
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/aio.c467
-rw-r--r--arch/um/os-Linux/main.c1
-rw-r--r--arch/um/os-Linux/process.c1
-rw-r--r--arch/um/os-Linux/signal.c158
-rw-r--r--arch/um/os-Linux/skas/Makefile10
-rw-r--r--arch/um/os-Linux/skas/trap.c (renamed from arch/um/kernel/skas/trap_user.c)49
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/trap.c40
-rw-r--r--arch/um/os-Linux/tt.c15
-rw-r--r--arch/um/os-Linux/umid.c335
-rw-r--r--arch/um/sys-i386/signal.c1
55 files changed, 1536 insertions, 1476 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 1eb21de9d1..8ff3bcbce5 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -22,10 +22,6 @@ config SBUS
22config PCI 22config PCI
23 bool 23 bool
24 24
25config UID16
26 bool
27 default y
28
29config GENERIC_CALIBRATE_DELAY 25config GENERIC_CALIBRATE_DELAY
30 bool 26 bool
31 default y 27 default y
@@ -39,12 +35,12 @@ menu "UML-specific options"
39 35
40config MODE_TT 36config MODE_TT
41 bool "Tracing thread support" 37 bool "Tracing thread support"
42 default y 38 default n
43 help 39 help
44 This option controls whether tracing thread support is compiled 40 This option controls whether tracing thread support is compiled
45 into UML. Normally, this should be set to Y. If you intend to 41 into UML. This option is largely obsolete, given that skas0 provides
46 use only skas mode (and the host has the skas patch applied to it), 42 skas security and performance without needing to patch the host.
47 then it is OK to say N here. 43 It is safe to say 'N' here.
48 44
49config STATIC_LINK 45config STATIC_LINK
50 bool "Force a static link" 46 bool "Force a static link"
@@ -83,7 +79,7 @@ config KERNEL_HALF_GIGS
83 of physical memory. 79 of physical memory.
84 80
85config MODE_SKAS 81config MODE_SKAS
86 bool "Separate Kernel Address Space support" 82 bool "Separate Kernel Address Space support" if MODE_TT
87 default y 83 default y
88 help 84 help
89 This option controls whether skas (separate kernel address space) 85 This option controls whether skas (separate kernel address space)
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 1b12feeba3..322972fd06 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -189,6 +189,12 @@ define filechk_umlconfig
189 sed 's/ CONFIG/ UML_CONFIG/' 189 sed 's/ CONFIG/ UML_CONFIG/'
190endef 190endef
191 191
192$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
193 $(call filechk,umlconfig)
194
195$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
196 $(CC) $(USER_CFLAGS) -S -o $@ $<
197
192define filechk_gen-asm-offsets 198define filechk_gen-asm-offsets
193 (set -e; \ 199 (set -e; \
194 echo "/*"; \ 200 echo "/*"; \
@@ -202,24 +208,13 @@ define filechk_gen-asm-offsets
202 echo ""; ) 208 echo ""; )
203endef 209endef
204 210
205$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
206 $(call filechk,umlconfig)
207
208$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
209 $(CC) $(USER_CFLAGS) -S -o $@ $<
210
211$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s 211$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
212 $(call filechk,gen-asm-offsets) 212 $(call filechk,gen-asm-offsets)
213 213
214CLEAN_FILES += $(ARCH_DIR)/user-offsets.s 214CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
215 215
216$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \ 216$(ARCH_DIR)/include/kern_constants.h:
217 archprepare 217 @echo ' SYMLINK $@'
218 $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $< 218 $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
219
220$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/kernel-offsets.s
221 $(call filechk,gen-asm-offsets)
222
223CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s
224 219
225export SUBARCH USER_CFLAGS OS 220export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 5b58fad452..ab0d0b1708 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 58{
59 my_puts("Using a channel type which is configured out of " 59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 60 "UML\n");
61 return(NULL); 61 return NULL;
62} 62}
63 63
64static int not_configged_open(int input, int output, int primary, void *data, 64static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
66{ 66{
67 my_puts("Using a channel type which is configured out of " 67 my_puts("Using a channel type which is configured out of "
68 "UML\n"); 68 "UML\n");
69 return(-ENODEV); 69 return -ENODEV;
70} 70}
71 71
72static void not_configged_close(int fd, void *data) 72static void not_configged_close(int fd, void *data)
@@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
79{ 79{
80 my_puts("Using a channel type which is configured out of " 80 my_puts("Using a channel type which is configured out of "
81 "UML\n"); 81 "UML\n");
82 return(-EIO); 82 return -EIO;
83} 83}
84 84
85static int not_configged_write(int fd, const char *buf, int len, void *data) 85static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 86{
87 my_puts("Using a channel type which is configured out of " 87 my_puts("Using a channel type which is configured out of "
88 "UML\n"); 88 "UML\n");
89 return(-EIO); 89 return -EIO;
90} 90}
91 91
92static int not_configged_console_write(int fd, const char *buf, int len) 92static int not_configged_console_write(int fd, const char *buf, int len)
93{ 93{
94 my_puts("Using a channel type which is configured out of " 94 my_puts("Using a channel type which is configured out of "
95 "UML\n"); 95 "UML\n");
96 return(-EIO); 96 return -EIO;
97} 97}
98 98
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 99static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
101{ 101{
102 my_puts("Using a channel type which is configured out of " 102 my_puts("Using a channel type which is configured out of "
103 "UML\n"); 103 "UML\n");
104 return(-ENODEV); 104 return -ENODEV;
105} 105}
106 106
107static void not_configged_free(void *data) 107static void not_configged_free(void *data)
@@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
135 n = os_read_file(fd, c_out, sizeof(*c_out)); 135 n = os_read_file(fd, c_out, sizeof(*c_out));
136 136
137 if(n == -EAGAIN) 137 if(n == -EAGAIN)
138 return(0); 138 return 0;
139 else if(n == 0) 139 else if(n == 0)
140 return(-EIO); 140 return -EIO;
141 return(n); 141 return n;
142} 142}
143 143
144/* XXX Trivial wrapper around os_write_file */ 144/* XXX Trivial wrapper around os_write_file */
145 145
146int generic_write(int fd, const char *buf, int n, void *unused) 146int generic_write(int fd, const char *buf, int n, void *unused)
147{ 147{
148 return(os_write_file(fd, buf, n)); 148 return os_write_file(fd, buf, n);
149} 149}
150 150
151int generic_window_size(int fd, void *unused, unsigned short *rows_out, 151int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
156 156
157 ret = os_window_size(fd, &rows, &cols); 157 ret = os_window_size(fd, &rows, &cols);
158 if(ret < 0) 158 if(ret < 0)
159 return(ret); 159 return ret;
160 160
161 ret = ((*rows_out != rows) || (*cols_out != cols)); 161 ret = ((*rows_out != rows) || (*cols_out != cols));
162 162
163 *rows_out = rows; 163 *rows_out = rows;
164 *cols_out = cols; 164 *cols_out = cols;
165 165
166 return(ret); 166 return ret;
167} 167}
168 168
169void generic_free(void *data) 169void generic_free(void *data)
@@ -186,25 +186,26 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
186 } 186 }
187 } 187 }
188 188
189 if((tty->flip.flag_buf_ptr == NULL) ||
190 (tty->flip.char_buf_ptr == NULL))
191 return;
192 tty_insert_flip_char(tty, ch, TTY_NORMAL); 189 tty_insert_flip_char(tty, ch, TTY_NORMAL);
193} 190}
194 191
195static int open_one_chan(struct chan *chan, int input, int output, int primary) 192static int open_one_chan(struct chan *chan)
196{ 193{
197 int fd; 194 int fd;
198 195
199 if(chan->opened) return(0); 196 if(chan->opened)
200 if(chan->ops->open == NULL) fd = 0; 197 return 0;
201 else fd = (*chan->ops->open)(input, output, primary, chan->data, 198
202 &chan->dev); 199 if(chan->ops->open == NULL)
203 if(fd < 0) return(fd); 200 fd = 0;
201 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
202 chan->data, &chan->dev);
203 if(fd < 0)
204 return fd;
204 chan->fd = fd; 205 chan->fd = fd;
205 206
206 chan->opened = 1; 207 chan->opened = 1;
207 return(0); 208 return 0;
208} 209}
209 210
210int open_chan(struct list_head *chans) 211int open_chan(struct list_head *chans)
@@ -215,11 +216,11 @@ int open_chan(struct list_head *chans)
215 216
216 list_for_each(ele, chans){ 217 list_for_each(ele, chans){
217 chan = list_entry(ele, struct chan, list); 218 chan = list_entry(ele, struct chan, list);
218 ret = open_one_chan(chan, chan->input, chan->output, 219 ret = open_one_chan(chan);
219 chan->primary); 220 if(chan->primary)
220 if(chan->primary) err = ret; 221 err = ret;
221 } 222 }
222 return(err); 223 return err;
223} 224}
224 225
225void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 226void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -236,20 +237,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
236 } 237 }
237} 238}
238 239
239void enable_chan(struct list_head *chans, struct tty_struct *tty) 240void enable_chan(struct line *line)
240{ 241{
241 struct list_head *ele; 242 struct list_head *ele;
242 struct chan *chan; 243 struct chan *chan;
243 244
244 list_for_each(ele, chans){ 245 list_for_each(ele, &line->chan_list){
245 chan = list_entry(ele, struct chan, list); 246 chan = list_entry(ele, struct chan, list);
246 if(!chan->opened) continue; 247 if(open_one_chan(chan))
248 continue;
247 249
248 line_setup_irq(chan->fd, chan->input, chan->output, tty); 250 if(chan->enabled)
251 continue;
252 line_setup_irq(chan->fd, chan->input, chan->output, line,
253 chan);
254 chan->enabled = 1;
249 } 255 }
250} 256}
251 257
252void close_chan(struct list_head *chans) 258static LIST_HEAD(irqs_to_free);
259
260void free_irqs(void)
261{
262 struct chan *chan;
263
264 while(!list_empty(&irqs_to_free)){
265 chan = list_entry(irqs_to_free.next, struct chan, free_list);
266 list_del(&chan->free_list);
267
268 if(chan->input)
269 free_irq(chan->line->driver->read_irq, chan);
270 if(chan->output)
271 free_irq(chan->line->driver->write_irq, chan);
272 chan->enabled = 0;
273 }
274}
275
276static void close_one_chan(struct chan *chan, int delay_free_irq)
277{
278 if(!chan->opened)
279 return;
280
281 if(delay_free_irq){
282 list_add(&chan->free_list, &irqs_to_free);
283 }
284 else {
285 if(chan->input)
286 free_irq(chan->line->driver->read_irq, chan);
287 if(chan->output)
288 free_irq(chan->line->driver->write_irq, chan);
289 chan->enabled = 0;
290 }
291 if(chan->ops->close != NULL)
292 (*chan->ops->close)(chan->fd, chan->data);
293
294 chan->opened = 0;
295 chan->fd = -1;
296}
297
298void close_chan(struct list_head *chans, int delay_free_irq)
253{ 299{
254 struct chan *chan; 300 struct chan *chan;
255 301
@@ -259,15 +305,37 @@ void close_chan(struct list_head *chans)
259 * so it must be the last closed. 305 * so it must be the last closed.
260 */ 306 */
261 list_for_each_entry_reverse(chan, chans, list) { 307 list_for_each_entry_reverse(chan, chans, list) {
262 if(!chan->opened) continue; 308 close_one_chan(chan, delay_free_irq);
263 if(chan->ops->close != NULL)
264 (*chan->ops->close)(chan->fd, chan->data);
265 chan->opened = 0;
266 chan->fd = -1;
267 } 309 }
268} 310}
269 311
270int write_chan(struct list_head *chans, const char *buf, int len, 312void deactivate_chan(struct list_head *chans, int irq)
313{
314 struct list_head *ele;
315
316 struct chan *chan;
317 list_for_each(ele, chans) {
318 chan = list_entry(ele, struct chan, list);
319
320 if(chan->enabled && chan->input)
321 deactivate_fd(chan->fd, irq);
322 }
323}
324
325void reactivate_chan(struct list_head *chans, int irq)
326{
327 struct list_head *ele;
328 struct chan *chan;
329
330 list_for_each(ele, chans) {
331 chan = list_entry(ele, struct chan, list);
332
333 if(chan->enabled && chan->input)
334 reactivate_fd(chan->fd, irq);
335 }
336}
337
338int write_chan(struct list_head *chans, const char *buf, int len,
271 int write_irq) 339 int write_irq)
272{ 340{
273 struct list_head *ele; 341 struct list_head *ele;
@@ -285,7 +353,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
285 reactivate_fd(chan->fd, write_irq); 353 reactivate_fd(chan->fd, write_irq);
286 } 354 }
287 } 355 }
288 return(ret); 356 return ret;
289} 357}
290 358
291int console_write_chan(struct list_head *chans, const char *buf, int len) 359int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -301,19 +369,18 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
301 n = chan->ops->console_write(chan->fd, buf, len); 369 n = chan->ops->console_write(chan->fd, buf, len);
302 if(chan->primary) ret = n; 370 if(chan->primary) ret = n;
303 } 371 }
304 return(ret); 372 return ret;
305} 373}
306 374
307int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 375int console_open_chan(struct line *line, struct console *co,
376 struct chan_opts *opts)
308{ 377{
309 if (!list_empty(&line->chan_list)) 378 int err;
310 return 0; 379
380 err = open_chan(&line->chan_list);
381 if(err)
382 return err;
311 383
312 if (0 != parse_chan_pair(line->init_str, &line->chan_list,
313 line->init_pri, co->index, opts))
314 return -1;
315 if (0 != open_chan(&line->chan_list))
316 return -1;
317 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 384 printk("Console initialized on /dev/%s%d\n",co->name,co->index);
318 return 0; 385 return 0;
319} 386}
@@ -327,32 +394,36 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
327 list_for_each(ele, chans){ 394 list_for_each(ele, chans){
328 chan = list_entry(ele, struct chan, list); 395 chan = list_entry(ele, struct chan, list);
329 if(chan->primary){ 396 if(chan->primary){
330 if(chan->ops->window_size == NULL) return(0); 397 if(chan->ops->window_size == NULL)
331 return(chan->ops->window_size(chan->fd, chan->data, 398 return 0;
332 rows_out, cols_out)); 399 return chan->ops->window_size(chan->fd, chan->data,
400 rows_out, cols_out);
333 } 401 }
334 } 402 }
335 return(0); 403 return 0;
336} 404}
337 405
338void free_one_chan(struct chan *chan) 406void free_one_chan(struct chan *chan, int delay_free_irq)
339{ 407{
340 list_del(&chan->list); 408 list_del(&chan->list);
409
410 close_one_chan(chan, delay_free_irq);
411
341 if(chan->ops->free != NULL) 412 if(chan->ops->free != NULL)
342 (*chan->ops->free)(chan->data); 413 (*chan->ops->free)(chan->data);
343 free_irq_by_fd(chan->fd); 414
344 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 415 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
345 kfree(chan); 416 kfree(chan);
346} 417}
347 418
348void free_chan(struct list_head *chans) 419void free_chan(struct list_head *chans, int delay_free_irq)
349{ 420{
350 struct list_head *ele, *next; 421 struct list_head *ele, *next;
351 struct chan *chan; 422 struct chan *chan;
352 423
353 list_for_each_safe(ele, next, chans){ 424 list_for_each_safe(ele, next, chans){
354 chan = list_entry(ele, struct chan, list); 425 chan = list_entry(ele, struct chan, list);
355 free_one_chan(chan); 426 free_one_chan(chan, delay_free_irq);
356 } 427 }
357} 428}
358 429
@@ -363,23 +434,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
363 434
364 if(chan == NULL){ 435 if(chan == NULL){
365 CONFIG_CHUNK(str, size, n, "none", 1); 436 CONFIG_CHUNK(str, size, n, "none", 1);
366 return(n); 437 return n;
367 } 438 }
368 439
369 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 440 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
370 441
371 if(chan->dev == NULL){ 442 if(chan->dev == NULL){
372 CONFIG_CHUNK(str, size, n, "", 1); 443 CONFIG_CHUNK(str, size, n, "", 1);
373 return(n); 444 return n;
374 } 445 }
375 446
376 CONFIG_CHUNK(str, size, n, ":", 0); 447 CONFIG_CHUNK(str, size, n, ":", 0);
377 CONFIG_CHUNK(str, size, n, chan->dev, 0); 448 CONFIG_CHUNK(str, size, n, chan->dev, 0);
378 449
379 return(n); 450 return n;
380} 451}
381 452
382static int chan_pair_config_string(struct chan *in, struct chan *out, 453static int chan_pair_config_string(struct chan *in, struct chan *out,
383 char *str, int size, char **error_out) 454 char *str, int size, char **error_out)
384{ 455{
385 int n; 456 int n;
@@ -390,7 +461,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
390 461
391 if(in == out){ 462 if(in == out){
392 CONFIG_CHUNK(str, size, n, "", 1); 463 CONFIG_CHUNK(str, size, n, "", 1);
393 return(n); 464 return n;
394 } 465 }
395 466
396 CONFIG_CHUNK(str, size, n, ",", 1); 467 CONFIG_CHUNK(str, size, n, ",", 1);
@@ -399,10 +470,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
399 size -= n; 470 size -= n;
400 CONFIG_CHUNK(str, size, n, "", 1); 471 CONFIG_CHUNK(str, size, n, "", 1);
401 472
402 return(n); 473 return n;
403} 474}
404 475
405int chan_config_string(struct list_head *chans, char *str, int size, 476int chan_config_string(struct list_head *chans, char *str, int size,
406 char **error_out) 477 char **error_out)
407{ 478{
408 struct list_head *ele; 479 struct list_head *ele;
@@ -418,7 +489,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
418 out = chan; 489 out = chan;
419 } 490 }
420 491
421 return(chan_pair_config_string(in, out, str, size, error_out)); 492 return chan_pair_config_string(in, out, str, size, error_out);
422} 493}
423 494
424struct chan_type { 495struct chan_type {
@@ -462,7 +533,7 @@ struct chan_type chan_table[] = {
462#endif 533#endif
463}; 534};
464 535
465static struct chan *parse_chan(char *str, int pri, int device, 536static struct chan *parse_chan(struct line *line, char *str, int device,
466 struct chan_opts *opts) 537 struct chan_opts *opts)
467{ 538{
468 struct chan_type *entry; 539 struct chan_type *entry;
@@ -484,36 +555,42 @@ static struct chan *parse_chan(char *str, int pri, int device,
484 if(ops == NULL){ 555 if(ops == NULL){
485 my_printf("parse_chan couldn't parse \"%s\"\n", 556 my_printf("parse_chan couldn't parse \"%s\"\n",
486 str); 557 str);
487 return(NULL); 558 return NULL;
488 } 559 }
489 if(ops->init == NULL) return(NULL); 560 if(ops->init == NULL)
561 return NULL;
490 data = (*ops->init)(str, device, opts); 562 data = (*ops->init)(str, device, opts);
491 if(data == NULL) return(NULL); 563 if(data == NULL)
564 return NULL;
492 565
493 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 566 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
494 if(chan == NULL) return(NULL); 567 if(chan == NULL)
568 return NULL;
495 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 569 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
570 .free_list =
571 LIST_HEAD_INIT(chan->free_list),
572 .line = line,
496 .primary = 1, 573 .primary = 1,
497 .input = 0, 574 .input = 0,
498 .output = 0, 575 .output = 0,
499 .opened = 0, 576 .opened = 0,
577 .enabled = 0,
500 .fd = -1, 578 .fd = -1,
501 .pri = pri,
502 .ops = ops, 579 .ops = ops,
503 .data = data }); 580 .data = data });
504 return(chan); 581 return chan;
505} 582}
506 583
507int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 584int parse_chan_pair(char *str, struct line *line, int device,
508 struct chan_opts *opts) 585 struct chan_opts *opts)
509{ 586{
587 struct list_head *chans = &line->chan_list;
510 struct chan *new, *chan; 588 struct chan *new, *chan;
511 char *in, *out; 589 char *in, *out;
512 590
513 if(!list_empty(chans)){ 591 if(!list_empty(chans)){
514 chan = list_entry(chans->next, struct chan, list); 592 chan = list_entry(chans->next, struct chan, list);
515 if(chan->pri >= pri) return(0); 593 free_chan(chans, 0);
516 free_chan(chans);
517 INIT_LIST_HEAD(chans); 594 INIT_LIST_HEAD(chans);
518 } 595 }
519 596
@@ -522,24 +599,30 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
522 in = str; 599 in = str;
523 *out = '\0'; 600 *out = '\0';
524 out++; 601 out++;
525 new = parse_chan(in, pri, device, opts); 602 new = parse_chan(line, in, device, opts);
526 if(new == NULL) return(-1); 603 if(new == NULL)
604 return -1;
605
527 new->input = 1; 606 new->input = 1;
528 list_add(&new->list, chans); 607 list_add(&new->list, chans);
529 608
530 new = parse_chan(out, pri, device, opts); 609 new = parse_chan(line, out, device, opts);
531 if(new == NULL) return(-1); 610 if(new == NULL)
611 return -1;
612
532 list_add(&new->list, chans); 613 list_add(&new->list, chans);
533 new->output = 1; 614 new->output = 1;
534 } 615 }
535 else { 616 else {
536 new = parse_chan(str, pri, device, opts); 617 new = parse_chan(line, str, device, opts);
537 if(new == NULL) return(-1); 618 if(new == NULL)
619 return -1;
620
538 list_add(&new->list, chans); 621 list_add(&new->list, chans);
539 new->input = 1; 622 new->input = 1;
540 new->output = 1; 623 new->output = 1;
541 } 624 }
542 return(0); 625 return 0;
543} 626}
544 627
545int chan_out_fd(struct list_head *chans) 628int chan_out_fd(struct list_head *chans)
@@ -550,9 +633,9 @@ int chan_out_fd(struct list_head *chans)
550 list_for_each(ele, chans){ 633 list_for_each(ele, chans){
551 chan = list_entry(ele, struct chan, list); 634 chan = list_entry(ele, struct chan, list);
552 if(chan->primary && chan->output) 635 if(chan->primary && chan->output)
553 return(chan->fd); 636 return chan->fd;
554 } 637 }
555 return(-1); 638 return -1;
556} 639}
557 640
558void chan_interrupt(struct list_head *chans, struct work_struct *task, 641void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -567,9 +650,8 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
567 chan = list_entry(ele, struct chan, list); 650 chan = list_entry(ele, struct chan, list);
568 if(!chan->input || (chan->ops->read == NULL)) continue; 651 if(!chan->input || (chan->ops->read == NULL)) continue;
569 do { 652 do {
570 if((tty != NULL) && 653 if (tty && !tty_buffer_request_room(tty, 1)) {
571 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 654 schedule_delayed_work(task, 1);
572 schedule_work(task);
573 goto out; 655 goto out;
574 } 656 }
575 err = chan->ops->read(chan->fd, &c, chan->data); 657 err = chan->ops->read(chan->fd, &c, chan->data);
@@ -582,29 +664,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
582 if(chan->primary){ 664 if(chan->primary){
583 if(tty != NULL) 665 if(tty != NULL)
584 tty_hangup(tty); 666 tty_hangup(tty);
585 line_disable(tty, irq); 667 close_chan(chans, 1);
586 close_chan(chans);
587 free_chan(chans);
588 return; 668 return;
589 } 669 }
590 else { 670 else close_one_chan(chan, 1);
591 if(chan->ops->close != NULL)
592 chan->ops->close(chan->fd, chan->data);
593 free_one_chan(chan);
594 }
595 } 671 }
596 } 672 }
597 out: 673 out:
598 if(tty) tty_flip_buffer_push(tty); 674 if(tty) tty_flip_buffer_push(tty);
599} 675}
600
601/*
602 * Overrides for Emacs so that we follow Linus's tabbing style.
603 * Emacs will notice this stuff at the end of the file and automatically
604 * adjust the settings for this buffer only. This must remain at the end
605 * of the file.
606 * ---------------------------------------------------------------------------
607 * Local variables:
608 * c-file-style: "linux"
609 * End:
610 */
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index e0fdffa2d5..46ceb25a99 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.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 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,11 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 if(!line->throttled)
40 chan_interrupt(&line->chan_list, &line->task, line->tty,
41 line->driver->read_irq);
40} 42}
41 43
42/* Returns the free space inside the ring buffer of this line. 44/* Returns the free space inside the ring buffer of this line.
@@ -124,7 +126,8 @@ static int buffer_data(struct line *line, const char *buf, int len)
124 if (len < end){ 126 if (len < end){
125 memcpy(line->tail, buf, len); 127 memcpy(line->tail, buf, len);
126 line->tail += len; 128 line->tail += len;
127 } else { 129 }
130 else {
128 /* The circular buffer is wrapping */ 131 /* The circular buffer is wrapping */
129 memcpy(line->tail, buf, end); 132 memcpy(line->tail, buf, end);
130 buf += end; 133 buf += end;
@@ -170,7 +173,7 @@ static int flush_buffer(struct line *line)
170 } 173 }
171 174
172 count = line->tail - line->head; 175 count = line->tail - line->head;
173 n = write_chan(&line->chan_list, line->head, count, 176 n = write_chan(&line->chan_list, line->head, count,
174 line->driver->write_irq); 177 line->driver->write_irq);
175 178
176 if(n < 0) 179 if(n < 0)
@@ -227,7 +230,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
227 if (err <= 0 && (err != -EAGAIN || !ret)) 230 if (err <= 0 && (err != -EAGAIN || !ret))
228 ret = err; 231 ret = err;
229 } else { 232 } else {
230 n = write_chan(&line->chan_list, buf, len, 233 n = write_chan(&line->chan_list, buf, len,
231 line->driver->write_irq); 234 line->driver->write_irq);
232 if (n < 0) { 235 if (n < 0) {
233 ret = n; 236 ret = n;
@@ -338,11 +341,36 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
338 return ret; 341 return ret;
339} 342}
340 343
344void line_throttle(struct tty_struct *tty)
345{
346 struct line *line = tty->driver_data;
347
348 deactivate_chan(&line->chan_list, line->driver->read_irq);
349 line->throttled = 1;
350}
351
352void line_unthrottle(struct tty_struct *tty)
353{
354 struct line *line = tty->driver_data;
355
356 line->throttled = 0;
357 chan_interrupt(&line->chan_list, &line->task, tty,
358 line->driver->read_irq);
359
360 /* Maybe there is enough stuff pending that calling the interrupt
361 * throttles us again. In this case, line->throttled will be 1
362 * again and we shouldn't turn the interrupt back on.
363 */
364 if(!line->throttled)
365 reactivate_chan(&line->chan_list, line->driver->read_irq);
366}
367
341static irqreturn_t line_write_interrupt(int irq, void *data, 368static irqreturn_t line_write_interrupt(int irq, void *data,
342 struct pt_regs *unused) 369 struct pt_regs *unused)
343{ 370{
344 struct tty_struct *tty = data; 371 struct chan *chan = data;
345 struct line *line = tty->driver_data; 372 struct line *line = chan->line;
373 struct tty_struct *tty = line->tty;
346 int err; 374 int err;
347 375
348 /* Interrupts are enabled here because we registered the interrupt with 376 /* Interrupts are enabled here because we registered the interrupt with
@@ -364,7 +392,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
364 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 392 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
365 (tty->ldisc.write_wakeup != NULL)) 393 (tty->ldisc.write_wakeup != NULL))
366 (tty->ldisc.write_wakeup)(tty); 394 (tty->ldisc.write_wakeup)(tty);
367 395
368 /* BLOCKING mode 396 /* BLOCKING mode
369 * In blocking mode, everything sleeps on tty->write_wait. 397 * In blocking mode, everything sleeps on tty->write_wait.
370 * Sleeping in the console driver would break non-blocking 398 * Sleeping in the console driver would break non-blocking
@@ -376,53 +404,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
376 return IRQ_HANDLED; 404 return IRQ_HANDLED;
377} 405}
378 406
379int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 407int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
380{ 408{
381 struct line *line = tty->driver_data;
382 struct line_driver *driver = line->driver; 409 struct line_driver *driver = line->driver;
383 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 410 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
384 411
385 if (input) 412 if (input)
386 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 413 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
387 line_interrupt, flags, 414 line_interrupt, flags,
388 driver->read_irq_name, tty); 415 driver->read_irq_name, data);
389 if (err) 416 if (err)
390 return err; 417 return err;
391 if (output) 418 if (output)
392 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 419 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
393 line_write_interrupt, flags, 420 line_write_interrupt, flags,
394 driver->write_irq_name, tty); 421 driver->write_irq_name, data);
395 line->have_irq = 1; 422 line->have_irq = 1;
396 return err; 423 return err;
397} 424}
398 425
399void line_disable(struct tty_struct *tty, int current_irq) 426int line_open(struct line *lines, struct tty_struct *tty)
400{
401 struct line *line = tty->driver_data;
402
403 if(!line->have_irq)
404 return;
405
406 if(line->driver->read_irq == current_irq)
407 free_irq_later(line->driver->read_irq, tty);
408 else {
409 free_irq(line->driver->read_irq, tty);
410 }
411
412 if(line->driver->write_irq == current_irq)
413 free_irq_later(line->driver->write_irq, tty);
414 else {
415 free_irq(line->driver->write_irq, tty);
416 }
417
418 line->have_irq = 0;
419}
420
421int line_open(struct line *lines, struct tty_struct *tty,
422 struct chan_opts *opts)
423{ 427{
424 struct line *line; 428 struct line *line;
425 int err = 0; 429 int err = -ENODEV;
426 430
427 line = &lines[tty->index]; 431 line = &lines[tty->index];
428 tty->driver_data = line; 432 tty->driver_data = line;
@@ -430,31 +434,29 @@ int line_open(struct line *lines, struct tty_struct *tty,
430 /* The IRQ which takes this lock is not yet enabled and won't be run 434 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 435 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 436 spin_lock(&line->lock);
433 if (tty->count == 1) { 437
434 if (!line->valid) { 438 tty->driver_data = line;
435 err = -ENODEV; 439 line->tty = tty;
436 goto out; 440 if(!line->valid)
437 } 441 goto out;
438 if (list_empty(&line->chan_list)) { 442
439 err = parse_chan_pair(line->init_str, &line->chan_list, 443 if(tty->count == 1){
440 line->init_pri, tty->index, opts); 444 /* Here the device is opened, if necessary, and interrupt
441 if(err) goto out; 445 * is registered.
442 err = open_chan(&line->chan_list); 446 */
443 if(err) goto out; 447 enable_chan(line);
448 INIT_WORK(&line->task, line_timer_cb, line);
449
450 if(!line->sigio){
451 chan_enable_winch(&line->chan_list, tty);
452 line->sigio = 1;
444 } 453 }
445 /* Here the interrupt is registered.*/
446 enable_chan(&line->chan_list, tty);
447 INIT_WORK(&line->task, line_timer_cb, tty);
448 }
449 454
450 if(!line->sigio){ 455 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
451 chan_enable_winch(&line->chan_list, tty); 456 &tty->winsize.ws_col);
452 line->sigio = 1;
453 } 457 }
454 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
455 &tty->winsize.ws_col);
456 line->count++;
457 458
459 err = 0;
458out: 460out:
459 spin_unlock(&line->lock); 461 spin_unlock(&line->lock);
460 return err; 462 return err;
@@ -474,15 +476,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
474 /* We ignore the error anyway! */ 476 /* We ignore the error anyway! */
475 flush_buffer(line); 477 flush_buffer(line);
476 478
477 line->count--; 479 if(tty->count == 1){
478 if (tty->count == 1) { 480 line->tty = NULL;
479 line_disable(tty, -1);
480 tty->driver_data = NULL; 481 tty->driver_data = NULL;
481 }
482 482
483 if((line->count == 0) && line->sigio){ 483 if(line->sigio){
484 unregister_winch(tty); 484 unregister_winch(tty);
485 line->sigio = 0; 485 line->sigio = 0;
486 }
486 } 487 }
487 488
488 spin_unlock_irq(&line->lock); 489 spin_unlock_irq(&line->lock);
@@ -493,17 +494,15 @@ void close_lines(struct line *lines, int nlines)
493 int i; 494 int i;
494 495
495 for(i = 0; i < nlines; i++) 496 for(i = 0; i < nlines; i++)
496 close_chan(&lines[i].chan_list); 497 close_chan(&lines[i].chan_list, 0);
497} 498}
498 499
499/* Common setup code for both startup command line and mconsole initialization. 500/* Common setup code for both startup command line and mconsole initialization.
500 * @lines contains the the array (of size @num) to modify; 501 * @lines contains the the array (of size @num) to modify;
501 * @init is the setup string; 502 * @init is the setup string;
502 * @all_allowed is a boolean saying if we can setup the whole @lines 503 */
503 * at once. For instance, it will be usually true for startup init. (where we
504 * can use con=xterm) and false for mconsole.*/
505 504
506int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) 505int line_setup(struct line *lines, unsigned int num, char *init)
507{ 506{
508 int i, n; 507 int i, n;
509 char *end; 508 char *end;
@@ -512,10 +511,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
512 /* We said con=/ssl= instead of con#=, so we are configuring all 511 /* We said con=/ssl= instead of con#=, so we are configuring all
513 * consoles at once.*/ 512 * consoles at once.*/
514 n = -1; 513 n = -1;
515 } else { 514 }
515 else {
516 n = simple_strtoul(init, &end, 0); 516 n = simple_strtoul(init, &end, 0);
517 if(*end != '='){ 517 if(*end != '='){
518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
519 init); 519 init);
520 return 0; 520 return 0;
521 } 521 }
@@ -527,8 +527,9 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
528 n, num - 1); 528 n, num - 1);
529 return 0; 529 return 0;
530 } else if (n >= 0){ 530 }
531 if (lines[n].count > 0) { 531 else if (n >= 0){
532 if (lines[n].tty != NULL) {
532 printk("line_setup - device %d is open\n", n); 533 printk("line_setup - device %d is open\n", n);
533 return 0; 534 return 0;
534 } 535 }
@@ -539,13 +540,10 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
539 else { 540 else {
540 lines[n].init_str = init; 541 lines[n].init_str = init;
541 lines[n].valid = 1; 542 lines[n].valid = 1;
542 } 543 }
543 } 544 }
544 } else if(!all_allowed){ 545 }
545 printk("line_setup - can't configure all devices from " 546 else {
546 "mconsole\n");
547 return 0;
548 } else {
549 for(i = 0; i < num; i++){ 547 for(i = 0; i < num; i++){
550 if(lines[i].init_pri <= INIT_ALL){ 548 if(lines[i].init_pri <= INIT_ALL){
551 lines[i].init_pri = INIT_ALL; 549 lines[i].init_pri = INIT_ALL;
@@ -557,18 +555,33 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
557 } 555 }
558 } 556 }
559 } 557 }
560 return 1; 558 return n == -1 ? num : n;
561} 559}
562 560
563int line_config(struct line *lines, unsigned int num, char *str) 561int line_config(struct line *lines, unsigned int num, char *str,
562 struct chan_opts *opts)
564{ 563{
565 char *new = uml_strdup(str); 564 struct line *line;
565 char *new;
566 int n;
566 567
568 if(*str == '='){
569 printk("line_config - can't configure all devices from "
570 "mconsole\n");
571 return 1;
572 }
573
574 new = kstrdup(str, GFP_KERNEL);
567 if(new == NULL){ 575 if(new == NULL){
568 printk("line_config - uml_strdup failed\n"); 576 printk("line_config - kstrdup failed\n");
569 return -ENOMEM; 577 return 1;
570 } 578 }
571 return !line_setup(lines, num, new, 0); 579 n = line_setup(lines, num, new);
580 if(n < 0)
581 return 1;
582
583 line = &lines[n];
584 return parse_chan_pair(line->init_str, line, n, opts);
572} 585}
573 586
574int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 587int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -594,7 +607,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
594 spin_lock(&line->lock); 607 spin_lock(&line->lock);
595 if(!line->valid) 608 if(!line->valid)
596 CONFIG_CHUNK(str, size, n, "none", 1); 609 CONFIG_CHUNK(str, size, n, "none", 1);
597 else if(line->count == 0) 610 else if(line->tty == NULL)
598 CONFIG_CHUNK(str, size, n, line->init_str, 1); 611 CONFIG_CHUNK(str, size, n, line->init_str, 1);
599 else n = chan_config_string(&line->chan_list, str, size, error_out); 612 else n = chan_config_string(&line->chan_list, str, size, error_out);
600 spin_unlock(&line->lock); 613 spin_unlock(&line->lock);
@@ -619,14 +632,18 @@ int line_id(char **str, int *start_out, int *end_out)
619 632
620int line_remove(struct line *lines, unsigned int num, int n) 633int line_remove(struct line *lines, unsigned int num, int n)
621{ 634{
635 int err;
622 char config[sizeof("conxxxx=none\0")]; 636 char config[sizeof("conxxxx=none\0")];
623 637
624 sprintf(config, "%d=none", n); 638 sprintf(config, "%d=none", n);
625 return !line_setup(lines, num, config, 0); 639 err = line_setup(lines, num, config);
640 if(err >= 0)
641 err = 0;
642 return err;
626} 643}
627 644
628struct tty_driver *line_register_devfs(struct lines *set, 645struct tty_driver *line_register_devfs(struct lines *set,
629 struct line_driver *line_driver, 646 struct line_driver *line_driver,
630 struct tty_operations *ops, struct line *lines, 647 struct tty_operations *ops, struct line *lines,
631 int nlines) 648 int nlines)
632{ 649{
@@ -655,7 +672,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
655 } 672 }
656 673
657 for(i = 0; i < nlines; i++){ 674 for(i = 0; i < nlines; i++){
658 if(!lines[i].valid) 675 if(!lines[i].valid)
659 tty_unregister_device(driver, i); 676 tty_unregister_device(driver, i);
660 } 677 }
661 678
@@ -663,24 +680,28 @@ struct tty_driver *line_register_devfs(struct lines *set,
663 return driver; 680 return driver;
664} 681}
665 682
666static spinlock_t winch_handler_lock; 683static DEFINE_SPINLOCK(winch_handler_lock);
667LIST_HEAD(winch_handlers); 684static LIST_HEAD(winch_handlers);
668 685
669void lines_init(struct line *lines, int nlines) 686void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
670{ 687{
671 struct line *line; 688 struct line *line;
672 int i; 689 int i;
673 690
674 spin_lock_init(&winch_handler_lock);
675 for(i = 0; i < nlines; i++){ 691 for(i = 0; i < nlines; i++){
676 line = &lines[i]; 692 line = &lines[i];
677 INIT_LIST_HEAD(&line->chan_list); 693 INIT_LIST_HEAD(&line->chan_list);
678 spin_lock_init(&line->lock); 694
679 if(line->init_str != NULL){ 695 if(line->init_str == NULL)
680 line->init_str = uml_strdup(line->init_str); 696 continue;
681 if(line->init_str == NULL) 697
682 printk("lines_init - uml_strdup returned " 698 line->init_str = kstrdup(line->init_str, GFP_KERNEL);
683 "NULL\n"); 699 if(line->init_str == NULL)
700 printk("lines_init - kstrdup returned NULL\n");
701
702 if(parse_chan_pair(line->init_str, line, i, opts)){
703 printk("parse_chan_pair failed for device %d\n", i);
704 line->valid = 0;
684 } 705 }
685 } 706 }
686} 707}
@@ -717,8 +738,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
717 tty = winch->tty; 738 tty = winch->tty;
718 if (tty != NULL) { 739 if (tty != NULL) {
719 line = tty->driver_data; 740 line = tty->driver_data;
720 chan_window_size(&line->chan_list, 741 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
721 &tty->winsize.ws_row,
722 &tty->winsize.ws_col); 742 &tty->winsize.ws_col);
723 kill_pg(tty->pgrp, SIGWINCH, 1); 743 kill_pg(tty->pgrp, SIGWINCH, 1);
724 } 744 }
@@ -749,60 +769,54 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
749 spin_unlock(&winch_handler_lock); 769 spin_unlock(&winch_handler_lock);
750 770
751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 771 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 772 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
753 "winch", winch) < 0) 773 "winch", winch) < 0)
754 printk("register_winch_irq - failed to register IRQ\n"); 774 printk("register_winch_irq - failed to register IRQ\n");
755} 775}
756 776
777static void free_winch(struct winch *winch)
778{
779 list_del(&winch->list);
780
781 if(winch->pid != -1)
782 os_kill_process(winch->pid, 1);
783 if(winch->fd != -1)
784 os_close_file(winch->fd);
785
786 free_irq(WINCH_IRQ, winch);
787 kfree(winch);
788}
789
757static void unregister_winch(struct tty_struct *tty) 790static void unregister_winch(struct tty_struct *tty)
758{ 791{
759 struct list_head *ele; 792 struct list_head *ele;
760 struct winch *winch, *found = NULL; 793 struct winch *winch;
761 794
762 spin_lock(&winch_handler_lock); 795 spin_lock(&winch_handler_lock);
796
763 list_for_each(ele, &winch_handlers){ 797 list_for_each(ele, &winch_handlers){
764 winch = list_entry(ele, struct winch, list); 798 winch = list_entry(ele, struct winch, list);
765 if(winch->tty == tty){ 799 if(winch->tty == tty){
766 found = winch; 800 free_winch(winch);
767 break; 801 break;
768 } 802 }
769 } 803 }
770 if(found == NULL)
771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
775
776 if(winch->pid != -1)
777 os_kill_process(winch->pid, 1);
778
779 free_irq(WINCH_IRQ, winch);
780 kfree(winch);
781
782 return;
783err:
784 spin_unlock(&winch_handler_lock); 804 spin_unlock(&winch_handler_lock);
785} 805}
786 806
787/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
788 * order... are we sure that nothing else is done on the list? */
789static void winch_cleanup(void) 807static void winch_cleanup(void)
790{ 808{
791 struct list_head *ele; 809 struct list_head *ele, *next;
792 struct winch *winch; 810 struct winch *winch;
793 811
794 list_for_each(ele, &winch_handlers){ 812 spin_lock(&winch_handler_lock);
813
814 list_for_each_safe(ele, next, &winch_handlers){
795 winch = list_entry(ele, struct winch, list); 815 winch = list_entry(ele, struct winch, list);
796 if(winch->fd != -1){ 816 free_winch(winch);
797 /* Why is this different from the above free_irq(),
798 * which deactivates SIGIO? This searches the FD
799 * somewhere else and removes it from the list... */
800 deactivate_fd(winch->fd, WINCH_IRQ);
801 os_close_file(winch->fd);
802 }
803 if(winch->pid != -1)
804 os_kill_process(winch->pid, 1);
805 } 817 }
818
819 spin_unlock(&winch_handler_lock);
806} 820}
807__uml_exitcall(winch_cleanup); 821__uml_exitcall(winch_cleanup);
808 822
@@ -811,10 +825,10 @@ char *add_xterm_umid(char *base)
811 char *umid, *title; 825 char *umid, *title;
812 int len; 826 int len;
813 827
814 umid = get_umid(1); 828 umid = get_umid();
815 if(umid == NULL) 829 if(*umid == '\0')
816 return base; 830 return base;
817 831
818 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 832 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
819 title = kmalloc(len, GFP_KERNEL); 833 title = kmalloc(len, GFP_KERNEL);
820 if(title == NULL){ 834 if(title == NULL){
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 12c9536812..e3d5765671 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,7 @@
20#include "linux/namei.h" 20#include "linux/namei.h"
21#include "linux/proc_fs.h" 21#include "linux/proc_fs.h"
22#include "linux/syscalls.h" 22#include "linux/syscalls.h"
23#include "linux/console.h"
23#include "asm/irq.h" 24#include "asm/irq.h"
24#include "asm/uaccess.h" 25#include "asm/uaccess.h"
25#include "user_util.h" 26#include "user_util.h"
@@ -34,7 +35,7 @@
34#include "irq_kern.h" 35#include "irq_kern.h"
35#include "choose-mode.h" 36#include "choose-mode.h"
36 37
37static int do_unlink_socket(struct notifier_block *notifier, 38static int do_unlink_socket(struct notifier_block *notifier,
38 unsigned long what, void *data) 39 unsigned long what, void *data)
39{ 40{
40 return(mconsole_unlink_socket()); 41 return(mconsole_unlink_socket());
@@ -46,12 +47,12 @@ static struct notifier_block reboot_notifier = {
46 .priority = 0, 47 .priority = 0,
47}; 48};
48 49
49/* Safe without explicit locking for now. Tasklets provide their own 50/* Safe without explicit locking for now. Tasklets provide their own
50 * locking, and the interrupt handler is safe because it can't interrupt 51 * locking, and the interrupt handler is safe because it can't interrupt
51 * itself and it can only happen on CPU 0. 52 * itself and it can only happen on CPU 0.
52 */ 53 */
53 54
54LIST_HEAD(mc_requests); 55static LIST_HEAD(mc_requests);
55 56
56static void mc_work_proc(void *unused) 57static void mc_work_proc(void *unused)
57{ 58{
@@ -60,7 +61,7 @@ static void mc_work_proc(void *unused)
60 61
61 while(!list_empty(&mc_requests)){ 62 while(!list_empty(&mc_requests)){
62 local_save_flags(flags); 63 local_save_flags(flags);
63 req = list_entry(mc_requests.next, struct mconsole_entry, 64 req = list_entry(mc_requests.next, struct mconsole_entry,
64 list); 65 list);
65 list_del(&req->list); 66 list_del(&req->list);
66 local_irq_restore(flags); 67 local_irq_restore(flags);
@@ -69,7 +70,7 @@ static void mc_work_proc(void *unused)
69 } 70 }
70} 71}
71 72
72DECLARE_WORK(mconsole_work, mc_work_proc, NULL); 73static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
73 74
74static irqreturn_t mconsole_interrupt(int irq, void *dev_id, 75static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
75 struct pt_regs *regs) 76 struct pt_regs *regs)
@@ -103,8 +104,8 @@ void mconsole_version(struct mc_request *req)
103{ 104{
104 char version[256]; 105 char version[256];
105 106
106 sprintf(version, "%s %s %s %s %s", system_utsname.sysname, 107 sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
107 system_utsname.nodename, system_utsname.release, 108 system_utsname.nodename, system_utsname.release,
108 system_utsname.version, system_utsname.machine); 109 system_utsname.version, system_utsname.machine);
109 mconsole_reply(req, version, 0, 0); 110 mconsole_reply(req, version, 0, 0);
110} 111}
@@ -348,7 +349,7 @@ static struct mc_device *mconsole_find_dev(char *name)
348 349
349#define CONFIG_BUF_SIZE 64 350#define CONFIG_BUF_SIZE 64
350 351
351static void mconsole_get_config(int (*get_config)(char *, char *, int, 352static void mconsole_get_config(int (*get_config)(char *, char *, int,
352 char **), 353 char **),
353 struct mc_request *req, char *name) 354 struct mc_request *req, char *name)
354{ 355{
@@ -389,7 +390,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
389 out: 390 out:
390 if(buf != default_buf) 391 if(buf != default_buf)
391 kfree(buf); 392 kfree(buf);
392
393} 393}
394 394
395void mconsole_config(struct mc_request *req) 395void mconsole_config(struct mc_request *req)
@@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req)
420 420
421void mconsole_remove(struct mc_request *req) 421void mconsole_remove(struct mc_request *req)
422{ 422{
423 struct mc_device *dev; 423 struct mc_device *dev;
424 char *ptr = req->request.data, *err_msg = ""; 424 char *ptr = req->request.data, *err_msg = "";
425 char error[256]; 425 char error[256];
426 int err, start, end, n; 426 int err, start, end, n;
427 427
428 ptr += strlen("remove"); 428 ptr += strlen("remove");
@@ -433,37 +433,112 @@ void mconsole_remove(struct mc_request *req)
433 return; 433 return;
434 } 434 }
435 435
436 ptr = &ptr[strlen(dev->name)]; 436 ptr = &ptr[strlen(dev->name)];
437 437
438 err = 1; 438 err = 1;
439 n = (*dev->id)(&ptr, &start, &end); 439 n = (*dev->id)(&ptr, &start, &end);
440 if(n < 0){ 440 if(n < 0){
441 err_msg = "Couldn't parse device number"; 441 err_msg = "Couldn't parse device number";
442 goto out; 442 goto out;
443 } 443 }
444 else if((n < start) || (n > end)){ 444 else if((n < start) || (n > end)){
445 sprintf(error, "Invalid device number - must be between " 445 sprintf(error, "Invalid device number - must be between "
446 "%d and %d", start, end); 446 "%d and %d", start, end);
447 err_msg = error; 447 err_msg = error;
448 goto out; 448 goto out;
449 } 449 }
450 450
451 err = (*dev->remove)(n); 451 err = (*dev->remove)(n);
452 switch(err){ 452 switch(err){
453 case -ENODEV: 453 case -ENODEV:
454 err_msg = "Device doesn't exist"; 454 err_msg = "Device doesn't exist";
455 break; 455 break;
456 case -EBUSY: 456 case -EBUSY:
457 err_msg = "Device is currently open"; 457 err_msg = "Device is currently open";
458 break; 458 break;
459 default: 459 default:
460 break; 460 break;
461 } 461 }
462 out: 462out:
463 mconsole_reply(req, err_msg, err, 0); 463 mconsole_reply(req, err_msg, err, 0);
464} 464}
465 465
466static DEFINE_SPINLOCK(console_lock);
467static LIST_HEAD(clients);
468static char console_buf[MCONSOLE_MAX_DATA];
469static int console_index = 0;
470
471static void console_write(struct console *console, const char *string,
472 unsigned len)
473{
474 struct list_head *ele;
475 int n;
476
477 if(list_empty(&clients))
478 return;
479
480 while(1){
481 n = min(len, ARRAY_SIZE(console_buf) - console_index);
482 strncpy(&console_buf[console_index], string, n);
483 console_index += n;
484 string += n;
485 len -= n;
486 if(len == 0)
487 return;
488
489 list_for_each(ele, &clients){
490 struct mconsole_entry *entry;
491
492 entry = list_entry(ele, struct mconsole_entry, list);
493 mconsole_reply_len(&entry->request, console_buf,
494 console_index, 0, 1);
495 }
496
497 console_index = 0;
498 }
499}
500
501static struct console mc_console = { .name = "mc",
502 .write = console_write,
503 .flags = CON_ENABLED,
504 .index = -1 };
505
506static int mc_add_console(void)
507{
508 register_console(&mc_console);
509 return 0;
510}
511
512late_initcall(mc_add_console);
513
514static void with_console(struct mc_request *req, void (*proc)(void *),
515 void *arg)
516{
517 struct mconsole_entry entry;
518 unsigned long flags;
519
520 INIT_LIST_HEAD(&entry.list);
521 entry.request = *req;
522 list_add(&entry.list, &clients);
523 spin_lock_irqsave(&console_lock, flags);
524
525 (*proc)(arg);
526
527 mconsole_reply_len(req, console_buf, console_index, 0, 0);
528 console_index = 0;
529
530 spin_unlock_irqrestore(&console_lock, flags);
531 list_del(&entry.list);
532}
533
466#ifdef CONFIG_MAGIC_SYSRQ 534#ifdef CONFIG_MAGIC_SYSRQ
535static void sysrq_proc(void *arg)
536{
537 char *op = arg;
538
539 handle_sysrq(*op, &current->thread.regs, NULL);
540}
541
467void mconsole_sysrq(struct mc_request *req) 542void mconsole_sysrq(struct mc_request *req)
468{ 543{
469 char *ptr = req->request.data; 544 char *ptr = req->request.data;
@@ -471,8 +546,13 @@ void mconsole_sysrq(struct mc_request *req)
471 ptr += strlen("sysrq"); 546 ptr += strlen("sysrq");
472 while(isspace(*ptr)) ptr++; 547 while(isspace(*ptr)) ptr++;
473 548
474 mconsole_reply(req, "", 0, 0); 549 /* With 'b', the system will shut down without a chance to reply,
475 handle_sysrq(*ptr, &current->thread.regs, NULL); 550 * so in this case, we reply first.
551 */
552 if(*ptr == 'b')
553 mconsole_reply(req, "", 0, 0);
554
555 with_console(req, sysrq_proc, ptr);
476} 556}
477#else 557#else
478void mconsole_sysrq(struct mc_request *req) 558void mconsole_sysrq(struct mc_request *req)
@@ -481,6 +561,14 @@ void mconsole_sysrq(struct mc_request *req)
481} 561}
482#endif 562#endif
483 563
564static void stack_proc(void *arg)
565{
566 struct task_struct *from = current, *to = arg;
567
568 to->thread.saved_task = from;
569 switch_to(from, to, from);
570}
571
484/* Mconsole stack trace 572/* Mconsole stack trace
485 * Added by Allan Graves, Jeff Dike 573 * Added by Allan Graves, Jeff Dike
486 * Dumps a stacks registers to the linux console. 574 * Dumps a stacks registers to the linux console.
@@ -488,37 +576,34 @@ void mconsole_sysrq(struct mc_request *req)
488 */ 576 */
489void do_stack(struct mc_request *req) 577void do_stack(struct mc_request *req)
490{ 578{
491 char *ptr = req->request.data; 579 char *ptr = req->request.data;
492 int pid_requested= -1; 580 int pid_requested= -1;
493 struct task_struct *from = NULL; 581 struct task_struct *from = NULL;
494 struct task_struct *to = NULL; 582 struct task_struct *to = NULL;
495 583
496 /* Would be nice: 584 /* Would be nice:
497 * 1) Send showregs output to mconsole. 585 * 1) Send showregs output to mconsole.
498 * 2) Add a way to stack dump all pids. 586 * 2) Add a way to stack dump all pids.
499 */ 587 */
500 588
501 ptr += strlen("stack"); 589 ptr += strlen("stack");
502 while(isspace(*ptr)) ptr++; 590 while(isspace(*ptr)) ptr++;
503
504 /* Should really check for multiple pids or reject bad args here */
505 /* What do the arguments in mconsole_reply mean? */
506 if(sscanf(ptr, "%d", &pid_requested) == 0){
507 mconsole_reply(req, "Please specify a pid", 1, 0);
508 return;
509 }
510 591
511 from = current; 592 /* Should really check for multiple pids or reject bad args here */
512 to = find_task_by_pid(pid_requested); 593 /* What do the arguments in mconsole_reply mean? */
594 if(sscanf(ptr, "%d", &pid_requested) == 0){
595 mconsole_reply(req, "Please specify a pid", 1, 0);
596 return;
597 }
513 598
514 if((to == NULL) || (pid_requested == 0)) { 599 from = current;
515 mconsole_reply(req, "Couldn't find that pid", 1, 0);
516 return;
517 }
518 to->thread.saved_task = current;
519 600
520 switch_to(from, to, from); 601 to = find_task_by_pid(pid_requested);
521 mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); 602 if((to == NULL) || (pid_requested == 0)) {
603 mconsole_reply(req, "Couldn't find that pid", 1, 0);
604 return;
605 }
606 with_console(req, stack_proc, to);
522} 607}
523 608
524void mconsole_stack(struct mc_request *req) 609void mconsole_stack(struct mc_request *req)
@@ -534,9 +619,9 @@ void mconsole_stack(struct mc_request *req)
534/* Changed by mconsole_setup, which is __setup, and called before SMP is 619/* Changed by mconsole_setup, which is __setup, and called before SMP is
535 * active. 620 * active.
536 */ 621 */
537static char *notify_socket = NULL; 622static char *notify_socket = NULL;
538 623
539int mconsole_init(void) 624static int mconsole_init(void)
540{ 625{
541 /* long to avoid size mismatch warnings from gcc */ 626 /* long to avoid size mismatch warnings from gcc */
542 long sock; 627 long sock;
@@ -563,16 +648,16 @@ int mconsole_init(void)
563 } 648 }
564 649
565 if(notify_socket != NULL){ 650 if(notify_socket != NULL){
566 notify_socket = uml_strdup(notify_socket); 651 notify_socket = kstrdup(notify_socket, GFP_KERNEL);
567 if(notify_socket != NULL) 652 if(notify_socket != NULL)
568 mconsole_notify(notify_socket, MCONSOLE_SOCKET, 653 mconsole_notify(notify_socket, MCONSOLE_SOCKET,
569 mconsole_socket_name, 654 mconsole_socket_name,
570 strlen(mconsole_socket_name) + 1); 655 strlen(mconsole_socket_name) + 1);
571 else printk(KERN_ERR "mconsole_setup failed to strdup " 656 else printk(KERN_ERR "mconsole_setup failed to strdup "
572 "string\n"); 657 "string\n");
573 } 658 }
574 659
575 printk("mconsole (version %d) initialized on %s\n", 660 printk("mconsole (version %d) initialized on %s\n",
576 MCONSOLE_VERSION, mconsole_socket_name); 661 MCONSOLE_VERSION, mconsole_socket_name);
577 return(0); 662 return(0);
578} 663}
@@ -585,7 +670,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
585 char *buf; 670 char *buf;
586 671
587 buf = kmalloc(count + 1, GFP_KERNEL); 672 buf = kmalloc(count + 1, GFP_KERNEL);
588 if(buf == NULL) 673 if(buf == NULL)
589 return(-ENOMEM); 674 return(-ENOMEM);
590 675
591 if(copy_from_user(buf, buffer, count)){ 676 if(copy_from_user(buf, buffer, count)){
@@ -661,7 +746,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
661 746
662 if(notify_socket == NULL) return(0); 747 if(notify_socket == NULL) return(0);
663 748
664 mconsole_notify(notify_socket, MCONSOLE_PANIC, message, 749 mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
665 strlen(message) + 1); 750 strlen(message) + 1);
666 return(0); 751 return(0);
667} 752}
@@ -686,14 +771,3 @@ char *mconsole_notify_socket(void)
686} 771}
687 772
688EXPORT_SYMBOL(mconsole_notify_socket); 773EXPORT_SYMBOL(mconsole_notify_socket);
689
690/*
691 * Overrides for Emacs so that we follow Linus's tabbing style.
692 * Emacs will notice this stuff at the end of the file and automatically
693 * adjust the settings for this buffer only. This must remain at the end
694 * of the file.
695 * ---------------------------------------------------------------------------
696 * Local variables:
697 * c-file-style: "linux"
698 * End:
699 */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 310c1f823f..4b109fe7ff 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req)
122 return(1); 122 return(1);
123} 123}
124 124
125int mconsole_reply(struct mc_request *req, char *str, int err, int more) 125int mconsole_reply_len(struct mc_request *req, const char *str, int total,
126 int err, int more)
126{ 127{
127 struct mconsole_reply reply; 128 struct mconsole_reply reply;
128 int total, len, n; 129 int len, n;
129 130
130 total = strlen(str);
131 do { 131 do {
132 reply.err = err; 132 reply.err = err;
133 133
@@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
155 return(0); 155 return(0);
156} 156}
157 157
158int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
159{
160 return mconsole_reply_len(req, str, strlen(str), err, more);
161}
162
163
158int mconsole_unlink_socket(void) 164int mconsole_unlink_socket(void)
159{ 165{
160 unlink(mconsole_socket_name); 166 unlink(mconsole_socket_name);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 84c73a300a..fb1f9fb9b8 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -34,7 +34,7 @@
34#define DRIVER_NAME "uml-netdev" 34#define DRIVER_NAME "uml-netdev"
35 35
36static DEFINE_SPINLOCK(opened_lock); 36static DEFINE_SPINLOCK(opened_lock);
37LIST_HEAD(opened); 37static LIST_HEAD(opened);
38 38
39static int uml_net_rx(struct net_device *dev) 39static int uml_net_rx(struct net_device *dev)
40{ 40{
@@ -150,6 +150,7 @@ static int uml_net_close(struct net_device *dev)
150 if(lp->close != NULL) 150 if(lp->close != NULL)
151 (*lp->close)(lp->fd, &lp->user); 151 (*lp->close)(lp->fd, &lp->user);
152 lp->fd = -1; 152 lp->fd = -1;
153 list_del(&lp->list);
153 154
154 spin_unlock(&lp->lock); 155 spin_unlock(&lp->lock);
155 return 0; 156 return 0;
@@ -266,7 +267,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
266} 267}
267 268
268static DEFINE_SPINLOCK(devices_lock); 269static DEFINE_SPINLOCK(devices_lock);
269static struct list_head devices = LIST_HEAD_INIT(devices); 270static LIST_HEAD(devices);
270 271
271static struct platform_driver uml_net_driver = { 272static struct platform_driver uml_net_driver = {
272 .driver = { 273 .driver = {
@@ -586,7 +587,7 @@ static int net_config(char *str)
586 err = eth_parse(str, &n, &str); 587 err = eth_parse(str, &n, &str);
587 if(err) return(err); 588 if(err) return(err);
588 589
589 str = uml_strdup(str); 590 str = kstrdup(str, GFP_KERNEL);
590 if(str == NULL){ 591 if(str == NULL){
591 printk(KERN_ERR "net_config failed to strdup string\n"); 592 printk(KERN_ERR "net_config failed to strdup string\n");
592 return(-1); 593 return(-1);
@@ -715,6 +716,7 @@ static void close_devices(void)
715 716
716 list_for_each(ele, &opened){ 717 list_for_each(ele, &opened){
717 lp = list_entry(ele, struct uml_net_private, list); 718 lp = list_entry(ele, struct uml_net_private, list);
719 free_irq(lp->dev->irq, lp->dev);
718 if((lp->close != NULL) && (lp->fd >= 0)) 720 if((lp->close != NULL) && (lp->fd >= 0))
719 (*lp->close)(lp->fd, &lp->user); 721 (*lp->close)(lp->fd, &lp->user);
720 if(lp->remove != NULL) (*lp->remove)(&lp->user); 722 if(lp->remove != NULL) (*lp->remove)(&lp->user);
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 62e04ecfad..a32ef55cb2 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -69,7 +69,7 @@ static struct line_driver driver = {
69 .name = "ssl", 69 .name = "ssl",
70 .config = ssl_config, 70 .config = ssl_config,
71 .get_config = ssl_get_config, 71 .get_config = ssl_get_config,
72 .id = line_id, 72 .id = line_id,
73 .remove = ssl_remove, 73 .remove = ssl_remove,
74 }, 74 },
75}; 75};
@@ -84,26 +84,23 @@ static struct lines lines = LINES_INIT(NR_PORTS);
84 84
85static int ssl_config(char *str) 85static int ssl_config(char *str)
86{ 86{
87 return(line_config(serial_lines, 87 return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
88 sizeof(serial_lines)/sizeof(serial_lines[0]), str));
89} 88}
90 89
91static int ssl_get_config(char *dev, char *str, int size, char **error_out) 90static int ssl_get_config(char *dev, char *str, int size, char **error_out)
92{ 91{
93 return(line_get_config(dev, serial_lines, 92 return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
94 sizeof(serial_lines)/sizeof(serial_lines[0]), 93 size, error_out);
95 str, size, error_out));
96} 94}
97 95
98static int ssl_remove(int n) 96static int ssl_remove(int n)
99{ 97{
100 return line_remove(serial_lines, 98 return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
101 sizeof(serial_lines)/sizeof(serial_lines[0]), n);
102} 99}
103 100
104int ssl_open(struct tty_struct *tty, struct file *filp) 101int ssl_open(struct tty_struct *tty, struct file *filp)
105{ 102{
106 return line_open(serial_lines, tty, &opts); 103 return line_open(serial_lines, tty);
107} 104}
108 105
109#if 0 106#if 0
@@ -112,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
112 return; 109 return;
113} 110}
114 111
115static void ssl_throttle(struct tty_struct * tty)
116{
117 printk(KERN_ERR "Someone should implement ssl_throttle\n");
118}
119
120static void ssl_unthrottle(struct tty_struct * tty)
121{
122 printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
123}
124
125static void ssl_stop(struct tty_struct *tty) 112static void ssl_stop(struct tty_struct *tty)
126{ 113{
127 printk(KERN_ERR "Someone should implement ssl_stop\n"); 114 printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -148,9 +135,9 @@ static struct tty_operations ssl_ops = {
148 .flush_chars = line_flush_chars, 135 .flush_chars = line_flush_chars,
149 .set_termios = line_set_termios, 136 .set_termios = line_set_termios,
150 .ioctl = line_ioctl, 137 .ioctl = line_ioctl,
138 .throttle = line_throttle,
139 .unthrottle = line_unthrottle,
151#if 0 140#if 0
152 .throttle = ssl_throttle,
153 .unthrottle = ssl_unthrottle,
154 .stop = ssl_stop, 141 .stop = ssl_stop,
155 .start = ssl_start, 142 .start = ssl_start,
156 .hangup = ssl_hangup, 143 .hangup = ssl_hangup,
@@ -183,7 +170,7 @@ static int ssl_console_setup(struct console *co, char *options)
183{ 170{
184 struct line *line = &serial_lines[co->index]; 171 struct line *line = &serial_lines[co->index];
185 172
186 return console_open_chan(line,co,&opts); 173 return console_open_chan(line, co, &opts);
187} 174}
188 175
189static struct console ssl_cons = { 176static struct console ssl_cons = {
@@ -199,12 +186,13 @@ int ssl_init(void)
199{ 186{
200 char *new_title; 187 char *new_title;
201 188
202 printk(KERN_INFO "Initializing software serial port version %d\n", 189 printk(KERN_INFO "Initializing software serial port version %d\n",
203 ssl_version); 190 ssl_version);
204 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, 191 ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
205 serial_lines, ARRAY_SIZE(serial_lines)); 192 serial_lines,
193 ARRAY_SIZE(serial_lines));
206 194
207 lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); 195 lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
208 196
209 new_title = add_xterm_umid(opts.xterm_title); 197 new_title = add_xterm_umid(opts.xterm_title);
210 if (new_title != NULL) 198 if (new_title != NULL)
@@ -212,7 +200,7 @@ int ssl_init(void)
212 200
213 ssl_init_done = 1; 201 ssl_init_done = 1;
214 register_console(&ssl_cons); 202 register_console(&ssl_cons);
215 return(0); 203 return 0;
216} 204}
217late_initcall(ssl_init); 205late_initcall(ssl_init);
218 206
@@ -220,16 +208,13 @@ static void ssl_exit(void)
220{ 208{
221 if (!ssl_init_done) 209 if (!ssl_init_done)
222 return; 210 return;
223 close_lines(serial_lines, 211 close_lines(serial_lines, ARRAY_SIZE(serial_lines));
224 sizeof(serial_lines)/sizeof(serial_lines[0]));
225} 212}
226__uml_exitcall(ssl_exit); 213__uml_exitcall(ssl_exit);
227 214
228static int ssl_chan_setup(char *str) 215static int ssl_chan_setup(char *str)
229{ 216{
230 return(line_setup(serial_lines, 217 return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
231 sizeof(serial_lines)/sizeof(serial_lines[0]),
232 str, 1));
233} 218}
234 219
235__setup("ssl", ssl_chan_setup); 220__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 005aa6333b..61db8b2fc8 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -75,7 +75,7 @@ static struct line_driver driver = {
75 .name = "con", 75 .name = "con",
76 .config = con_config, 76 .config = con_config,
77 .get_config = con_get_config, 77 .get_config = con_get_config,
78 .id = line_id, 78 .id = line_id,
79 .remove = con_remove, 79 .remove = con_remove,
80 }, 80 },
81}; 81};
@@ -86,28 +86,27 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS);
86 * individual elements are protected by individual semaphores. 86 * individual elements are protected by individual semaphores.
87 */ 87 */
88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), 88struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
89 [ 1 ... MAX_TTYS - 1 ] = 89 [ 1 ... MAX_TTYS - 1 ] =
90 LINE_INIT(CONFIG_CON_CHAN, &driver) }; 90 LINE_INIT(CONFIG_CON_CHAN, &driver) };
91 91
92static int con_config(char *str) 92static int con_config(char *str)
93{ 93{
94 return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); 94 return line_config(vts, ARRAY_SIZE(vts), str, &opts);
95} 95}
96 96
97static int con_get_config(char *dev, char *str, int size, char **error_out) 97static int con_get_config(char *dev, char *str, int size, char **error_out)
98{ 98{
99 return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, 99 return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
100 size, error_out));
101} 100}
102 101
103static int con_remove(int n) 102static int con_remove(int n)
104{ 103{
105 return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); 104 return line_remove(vts, ARRAY_SIZE(vts), n);
106} 105}
107 106
108static int con_open(struct tty_struct *tty, struct file *filp) 107static int con_open(struct tty_struct *tty, struct file *filp)
109{ 108{
110 return line_open(vts, tty, &opts); 109 return line_open(vts, tty);
111} 110}
112 111
113static int con_init_done = 0; 112static int con_init_done = 0;
@@ -117,16 +116,18 @@ static struct tty_operations console_ops = {
117 .close = line_close, 116 .close = line_close,
118 .write = line_write, 117 .write = line_write,
119 .put_char = line_put_char, 118 .put_char = line_put_char,
120 .write_room = line_write_room, 119 .write_room = line_write_room,
121 .chars_in_buffer = line_chars_in_buffer, 120 .chars_in_buffer = line_chars_in_buffer,
122 .flush_buffer = line_flush_buffer, 121 .flush_buffer = line_flush_buffer,
123 .flush_chars = line_flush_chars, 122 .flush_chars = line_flush_chars,
124 .set_termios = line_set_termios, 123 .set_termios = line_set_termios,
125 .ioctl = line_ioctl, 124 .ioctl = line_ioctl,
125 .throttle = line_throttle,
126 .unthrottle = line_unthrottle,
126}; 127};
127 128
128static void uml_console_write(struct console *console, const char *string, 129static void uml_console_write(struct console *console, const char *string,
129 unsigned len) 130 unsigned len)
130{ 131{
131 struct line *line = &vts[console->index]; 132 struct line *line = &vts[console->index];
132 unsigned long flags; 133 unsigned long flags;
@@ -146,7 +147,7 @@ static int uml_console_setup(struct console *co, char *options)
146{ 147{
147 struct line *line = &vts[co->index]; 148 struct line *line = &vts[co->index];
148 149
149 return console_open_chan(line,co,&opts); 150 return console_open_chan(line, co, &opts);
150} 151}
151 152
152static struct console stdiocons = { 153static struct console stdiocons = {
@@ -156,7 +157,7 @@ static struct console stdiocons = {
156 .setup = uml_console_setup, 157 .setup = uml_console_setup,
157 .flags = CON_PRINTBUFFER, 158 .flags = CON_PRINTBUFFER,
158 .index = -1, 159 .index = -1,
159 .data = &vts, 160 .data = &vts,
160}; 161};
161 162
162int stdio_init(void) 163int stdio_init(void)
@@ -166,11 +167,11 @@ int stdio_init(void)
166 console_driver = line_register_devfs(&console_lines, &driver, 167 console_driver = line_register_devfs(&console_lines, &driver,
167 &console_ops, vts, 168 &console_ops, vts,
168 ARRAY_SIZE(vts)); 169 ARRAY_SIZE(vts));
169 if (NULL == console_driver) 170 if (console_driver == NULL)
170 return -1; 171 return -1;
171 printk(KERN_INFO "Initialized stdio console driver\n"); 172 printk(KERN_INFO "Initialized stdio console driver\n");
172 173
173 lines_init(vts, sizeof(vts)/sizeof(vts[0])); 174 lines_init(vts, ARRAY_SIZE(vts), &opts);
174 175
175 new_title = add_xterm_umid(opts.xterm_title); 176 new_title = add_xterm_umid(opts.xterm_title);
176 if(new_title != NULL) 177 if(new_title != NULL)
@@ -178,7 +179,7 @@ int stdio_init(void)
178 179
179 con_init_done = 1; 180 con_init_done = 1;
180 register_console(&stdiocons); 181 register_console(&stdiocons);
181 return(0); 182 return 0;
182} 183}
183late_initcall(stdio_init); 184late_initcall(stdio_init);
184 185
@@ -186,13 +187,13 @@ static void console_exit(void)
186{ 187{
187 if (!con_init_done) 188 if (!con_init_done)
188 return; 189 return;
189 close_lines(vts, sizeof(vts)/sizeof(vts[0])); 190 close_lines(vts, ARRAY_SIZE(vts));
190} 191}
191__uml_exitcall(console_exit); 192__uml_exitcall(console_exit);
192 193
193static int console_chan_setup(char *str) 194static int console_chan_setup(char *str)
194{ 195{
195 return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); 196 return line_setup(vts, ARRAY_SIZE(vts), str);
196} 197}
197__setup("con", console_chan_setup); 198__setup("con", console_chan_setup);
198__channel_help(console_chan_setup, "con"); 199__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93898917cb..7696f8d2d8 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp);
117static int ubd_release(struct inode * inode, struct file * file); 117static int ubd_release(struct inode * inode, struct file * file);
118static int ubd_ioctl(struct inode * inode, struct file * file, 118static int ubd_ioctl(struct inode * inode, struct file * file,
119 unsigned int cmd, unsigned long arg); 119 unsigned int cmd, unsigned long arg);
120static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
120 121
121#define MAX_DEV (8) 122#define MAX_DEV (8)
122 123
@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
125 .open = ubd_open, 126 .open = ubd_open,
126 .release = ubd_release, 127 .release = ubd_release,
127 .ioctl = ubd_ioctl, 128 .ioctl = ubd_ioctl,
129 .getgeo = ubd_getgeo,
128}; 130};
129 131
130/* Protected by the queue_lock */ 132/* Protected by the queue_lock */
@@ -706,7 +708,7 @@ static int ubd_config(char *str)
706{ 708{
707 int n, err; 709 int n, err;
708 710
709 str = uml_strdup(str); 711 str = kstrdup(str, GFP_KERNEL);
710 if(str == NULL){ 712 if(str == NULL){
711 printk(KERN_ERR "ubd_config failed to strdup string\n"); 713 printk(KERN_ERR "ubd_config failed to strdup string\n");
712 return(1); 714 return(1);
@@ -1058,10 +1060,19 @@ static void do_ubd_request(request_queue_t *q)
1058 } 1060 }
1059} 1061}
1060 1062
1063static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1064{
1065 struct ubd *dev = bdev->bd_disk->private_data;
1066
1067 geo->heads = 128;
1068 geo->sectors = 32;
1069 geo->cylinders = dev->size / (128 * 32 * 512);
1070 return 0;
1071}
1072
1061static int ubd_ioctl(struct inode * inode, struct file * file, 1073static int ubd_ioctl(struct inode * inode, struct file * file,
1062 unsigned int cmd, unsigned long arg) 1074 unsigned int cmd, unsigned long arg)
1063{ 1075{
1064 struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
1065 struct ubd *dev = inode->i_bdev->bd_disk->private_data; 1076 struct ubd *dev = inode->i_bdev->bd_disk->private_data;
1066 struct hd_driveid ubd_id = { 1077 struct hd_driveid ubd_id = {
1067 .cyls = 0, 1078 .cyls = 0,
@@ -1070,16 +1081,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1070 }; 1081 };
1071 1082
1072 switch (cmd) { 1083 switch (cmd) {
1073 struct hd_geometry g;
1074 struct cdrom_volctrl volume; 1084 struct cdrom_volctrl volume;
1075 case HDIO_GETGEO:
1076 if(!loc) return(-EINVAL);
1077 g.heads = 128;
1078 g.sectors = 32;
1079 g.cylinders = dev->size / (128 * 32 * 512);
1080 g.start = get_start_sect(inode->i_bdev);
1081 return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
1082
1083 case HDIO_GET_IDENTITY: 1085 case HDIO_GET_IDENTITY:
1084 ubd_id.cyls = dev->size / (128 * 32 * 512); 1086 ubd_id.cyls = dev->size / (128 * 32 * 512);
1085 if(copy_to_user((char __user *) arg, (char *) &ubd_id, 1087 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
@@ -1387,15 +1389,6 @@ int io_thread(void *arg)
1387 printk("io_thread - write failed, fd = %d, err = %d\n", 1389 printk("io_thread - write failed, fd = %d, err = %d\n",
1388 kernel_fd, -n); 1390 kernel_fd, -n);
1389 } 1391 }
1390}
1391 1392
1392/* 1393 return 0;
1393 * Overrides for Emacs so that we follow Linus's tabbing style. 1394}
1394 * Emacs will notice this stuff at the end of the file and automatically
1395 * adjust the settings for this buffer only. This must remain at the end
1396 * of the file.
1397 * ---------------------------------------------------------------------------
1398 * Local variables:
1399 * c-file-style: "linux"
1400 * End:
1401 */
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index da9a6717e7..1bb5e9d942 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -14,21 +14,23 @@
14 14
15struct chan { 15struct chan {
16 struct list_head list; 16 struct list_head list;
17 struct list_head free_list;
18 struct line *line;
17 char *dev; 19 char *dev;
18 unsigned int primary:1; 20 unsigned int primary:1;
19 unsigned int input:1; 21 unsigned int input:1;
20 unsigned int output:1; 22 unsigned int output:1;
21 unsigned int opened:1; 23 unsigned int opened:1;
24 unsigned int enabled:1;
22 int fd; 25 int fd;
23 enum chan_init_pri pri;
24 struct chan_ops *ops; 26 struct chan_ops *ops;
25 void *data; 27 void *data;
26}; 28};
27 29
28extern void chan_interrupt(struct list_head *chans, struct work_struct *task, 30extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
29 struct tty_struct *tty, int irq); 31 struct tty_struct *tty, int irq);
30extern int parse_chan_pair(char *str, struct list_head *chans, int pri, 32extern int parse_chan_pair(char *str, struct line *line, int device,
31 int device, struct chan_opts *opts); 33 struct chan_opts *opts);
32extern int open_chan(struct list_head *chans); 34extern int open_chan(struct list_head *chans);
33extern 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,
34 int write_irq); 36 int write_irq);
@@ -36,9 +38,11 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
36 int len); 38 int len);
37extern int console_open_chan(struct line *line, struct console *co, 39extern int console_open_chan(struct line *line, struct console *co,
38 struct chan_opts *opts); 40 struct chan_opts *opts);
39extern void close_chan(struct list_head *chans); 41extern void deactivate_chan(struct list_head *chans, int irq);
42extern void reactivate_chan(struct list_head *chans, int irq);
40extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); 43extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
41extern void enable_chan(struct list_head *chans, struct tty_struct *tty); 44extern void enable_chan(struct line *line);
45extern void close_chan(struct list_head *chans, int delay_free_irq);
42extern int chan_window_size(struct list_head *chans, 46extern int chan_window_size(struct list_head *chans,
43 unsigned short *rows_out, 47 unsigned short *rows_out,
44 unsigned short *cols_out); 48 unsigned short *cols_out);
@@ -47,14 +51,3 @@ extern int chan_config_string(struct list_head *chans, char *str, int size,
47 char **error_out); 51 char **error_out);
48 52
49#endif 53#endif
50
51/*
52 * Overrides for Emacs so that we follow Linus's tabbing style.
53 * Emacs will notice this stuff at the end of the file and automatically
54 * adjust the settings for this buffer only. This must remain at the end
55 * of the file.
56 * ---------------------------------------------------------------------------
57 * Local variables:
58 * c-file-style: "linux"
59 * End:
60 */
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
index f25fa83a5d..b87b36a87d 100644
--- a/arch/um/include/choose-mode.h
+++ b/arch/um/include/choose-mode.h
@@ -23,6 +23,9 @@ static inline void *__choose_mode(void *tt, void *skas) {
23 23
24#elif defined(UML_CONFIG_MODE_TT) 24#elif defined(UML_CONFIG_MODE_TT)
25#define CHOOSE_MODE(tt, skas) (tt) 25#define CHOOSE_MODE(tt, skas) (tt)
26
27#else
28#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
26#endif 29#endif
27 30
28#define CHOOSE_MODE_PROC(tt, skas, args...) \ 31#define CHOOSE_MODE_PROC(tt, skas, args...) \
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index f724b71721..b61deb8b36 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -18,19 +18,8 @@ extern int deactivate_all_fds(void);
18extern void forward_interrupts(int pid); 18extern void forward_interrupts(int pid);
19extern void init_irq_signals(int on_sigstack); 19extern void init_irq_signals(int on_sigstack);
20extern void forward_ipi(int fd, int pid); 20extern void forward_ipi(int fd, int pid);
21extern void free_irq_later(int irq, void *dev_id);
22extern int activate_ipi(int fd, int pid); 21extern int activate_ipi(int fd, int pid);
23extern unsigned long irq_lock(void); 22extern unsigned long irq_lock(void);
24extern void irq_unlock(unsigned long flags); 23extern void irq_unlock(unsigned long flags);
25#endif
26 24
27/* 25#endif
28 * Overrides for Emacs so that we follow Linus's tabbing style.
29 * Emacs will notice this stuff at the end of the file and automatically
30 * adjust the settings for this buffer only. This must remain at the end
31 * of the file.
32 * ---------------------------------------------------------------------------
33 * Local variables:
34 * c-file-style: "linux"
35 * End:
36 */
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 1e3170768b..7d223beccb 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -17,7 +17,7 @@ extern int errno;
17 17
18extern int clone(int (*proc)(void *), void *sp, int flags, void *data); 18extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
19extern int sleep(int); 19extern int sleep(int);
20extern int printf(char *fmt, ...); 20extern int printf(const char *fmt, ...);
21extern char *strerror(int errnum); 21extern char *strerror(int errnum);
22extern char *ptsname(int __fd); 22extern char *ptsname(int __fd);
23extern int munmap(void *, int); 23extern int munmap(void *, int);
@@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int);
35extern int pipe(int *); 35extern int pipe(int *);
36extern int sched_yield(void); 36extern int sched_yield(void);
37extern int ptrace(int op, int pid, long addr, long data); 37extern int ptrace(int op, int pid, long addr, long data);
38
38#endif 39#endif
39 40
40/*
41 * Overrides for Emacs so that we follow Linus's tabbing style.
42 * Emacs will notice this stuff at the end of the file and automatically
43 * adjust the settings for this buffer only. This must remain at the end
44 * of the file.
45 * ---------------------------------------------------------------------------
46 * Local variables:
47 * c-file-style: "linux"
48 * End:
49 */
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index e5fec55701..8f4e46d677 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -10,6 +10,19 @@
10#include "sysdep/ptrace.h" 10#include "sysdep/ptrace.h"
11#include "sysdep/faultinfo.h" 11#include "sysdep/faultinfo.h"
12 12
13typedef void (*kern_hndl)(int, union uml_pt_regs *);
14
15struct kern_handlers {
16 kern_hndl relay_signal;
17 kern_hndl winch;
18 kern_hndl bus_handler;
19 kern_hndl page_fault;
20 kern_hndl sigio_handler;
21 kern_hndl timer_handler;
22};
23
24extern struct kern_handlers handlinfo_kern;
25
13extern int ncpus; 26extern int ncpus;
14extern char *linux_prog; 27extern char *linux_prog;
15extern char *gdb_init; 28extern char *gdb_init;
@@ -51,8 +64,6 @@ extern void timer_handler(int sig, union uml_pt_regs *regs);
51extern int set_signals(int enable); 64extern int set_signals(int enable);
52extern void force_sigbus(void); 65extern void force_sigbus(void);
53extern int pid_to_processor_id(int pid); 66extern int pid_to_processor_id(int pid);
54extern void block_signals(void);
55extern void unblock_signals(void);
56extern void deliver_signals(void *t); 67extern void deliver_signals(void *t);
57extern int next_syscall_index(int max); 68extern int next_syscall_index(int max);
58extern int next_trap_index(int max); 69extern int next_trap_index(int max);
@@ -111,6 +122,8 @@ extern void arch_switch(void);
111extern void free_irq(unsigned int, void *); 122extern void free_irq(unsigned int, void *);
112extern int um_in_interrupt(void); 123extern int um_in_interrupt(void);
113extern int cpu(void); 124extern int cpu(void);
125extern void segv_handler(int sig, union uml_pt_regs *regs);
126extern void sigio_handler(int sig, union uml_pt_regs *regs);
114 127
115#endif 128#endif
116 129
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5323d22a6c..6f4d680dc1 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -32,11 +32,13 @@ struct line_driver {
32}; 32};
33 33
34struct line { 34struct line {
35 struct tty_struct *tty;
35 char *init_str; 36 char *init_str;
36 int init_pri; 37 int init_pri;
37 struct list_head chan_list; 38 struct list_head chan_list;
38 int valid; 39 int valid;
39 int count; 40 int count;
41 int throttled;
40 /*This lock is actually, mostly, local to*/ 42 /*This lock is actually, mostly, local to*/
41 spinlock_t lock; 43 spinlock_t lock;
42 44
@@ -58,14 +60,15 @@ struct line {
58#define LINE_INIT(str, d) \ 60#define LINE_INIT(str, d) \
59 { init_str : str, \ 61 { init_str : str, \
60 init_pri : INIT_STATIC, \ 62 init_pri : INIT_STATIC, \
61 chan_list : { }, \
62 valid : 1, \ 63 valid : 1, \
64 throttled : 0, \
65 lock : SPIN_LOCK_UNLOCKED, \
63 buffer : NULL, \ 66 buffer : NULL, \
64 head : NULL, \ 67 head : NULL, \
65 tail : NULL, \ 68 tail : NULL, \
66 sigio : 0, \ 69 sigio : 0, \
67 driver : d, \ 70 driver : d, \
68 have_irq : 0 } 71 have_irq : 0 }
69 72
70struct lines { 73struct lines {
71 int num; 74 int num;
@@ -74,11 +77,11 @@ struct lines {
74#define LINES_INIT(n) { num : n } 77#define LINES_INIT(n) { num : n }
75 78
76extern void line_close(struct tty_struct *tty, struct file * filp); 79extern void line_close(struct tty_struct *tty, struct file * filp);
77extern int line_open(struct line *lines, struct tty_struct *tty, 80extern int line_open(struct line *lines, struct tty_struct *tty);
78 struct chan_opts *opts); 81extern int line_setup(struct line *lines, unsigned int sizeof_lines,
79extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, 82 char *init);
80 int all_allowed); 83extern int line_write(struct tty_struct *tty, const unsigned char *buf,
81extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); 84 int len);
82extern void line_put_char(struct tty_struct *tty, unsigned char ch); 85extern void line_put_char(struct tty_struct *tty, unsigned char ch);
83extern void line_set_termios(struct tty_struct *tty, struct termios * old); 86extern void line_set_termios(struct tty_struct *tty, struct termios * old);
84extern int line_chars_in_buffer(struct tty_struct *tty); 87extern int line_chars_in_buffer(struct tty_struct *tty);
@@ -87,23 +90,27 @@ extern void line_flush_chars(struct tty_struct *tty);
87extern int line_write_room(struct tty_struct *tty); 90extern int line_write_room(struct tty_struct *tty);
88extern int line_ioctl(struct tty_struct *tty, struct file * file, 91extern int line_ioctl(struct tty_struct *tty, struct file * file,
89 unsigned int cmd, unsigned long arg); 92 unsigned int cmd, unsigned long arg);
93extern void line_throttle(struct tty_struct *tty);
94extern void line_unthrottle(struct tty_struct *tty);
90 95
91extern char *add_xterm_umid(char *base); 96extern char *add_xterm_umid(char *base);
92extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); 97extern int line_setup_irq(int fd, int input, int output, struct line *line,
98 void *data);
93extern void line_close_chan(struct line *line); 99extern void line_close_chan(struct line *line);
94extern void line_disable(struct tty_struct *tty, int current_irq); 100extern struct tty_driver * line_register_devfs(struct lines *set,
95extern struct tty_driver * line_register_devfs(struct lines *set, 101 struct line_driver *line_driver,
96 struct line_driver *line_driver,
97 struct tty_operations *driver, 102 struct tty_operations *driver,
98 struct line *lines, 103 struct line *lines,
99 int nlines); 104 int nlines);
100extern void lines_init(struct line *lines, int nlines); 105extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
101extern void close_lines(struct line *lines, int nlines); 106extern void close_lines(struct line *lines, int nlines);
102 107
103extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); 108extern int line_config(struct line *lines, unsigned int sizeof_lines,
109 char *str, struct chan_opts *opts);
104extern int line_id(char **str, int *start_out, int *end_out); 110extern int line_id(char **str, int *start_out, int *end_out);
105extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); 111extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
106extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, 112extern int line_get_config(char *dev, struct line *lines,
113 unsigned int sizeof_lines, char *str,
107 int size, char **error_out); 114 int size, char **error_out);
108 115
109#endif 116#endif
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index b1b512f470..58f67d3911 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -32,7 +32,7 @@ struct mconsole_reply {
32 32
33struct mconsole_notify { 33struct mconsole_notify {
34 u32 magic; 34 u32 magic;
35 u32 version; 35 u32 version;
36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, 36 enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
37 MCONSOLE_USER_NOTIFY } type; 37 MCONSOLE_USER_NOTIFY } type;
38 u32 len; 38 u32 len;
@@ -66,7 +66,9 @@ struct mc_request
66extern char mconsole_socket_name[]; 66extern char mconsole_socket_name[];
67 67
68extern int mconsole_unlink_socket(void); 68extern int mconsole_unlink_socket(void);
69extern int mconsole_reply(struct mc_request *req, char *reply, int err, 69extern int mconsole_reply_len(struct mc_request *req, const char *reply,
70 int len, int err, int more);
71extern int mconsole_reply(struct mc_request *req, const char *str, int err,
70 int more); 72 int more);
71 73
72extern void mconsole_version(struct mc_request *req); 74extern void mconsole_version(struct mc_request *req);
@@ -84,7 +86,7 @@ extern void mconsole_proc(struct mc_request *req);
84extern void mconsole_stack(struct mc_request *req); 86extern void mconsole_stack(struct mc_request *req);
85 87
86extern int mconsole_get_request(int fd, struct mc_request *req); 88extern int mconsole_get_request(int fd, struct mc_request *req);
87extern int mconsole_notify(char *sock_name, int type, const void *data, 89extern int mconsole_notify(char *sock_name, int type, const void *data,
88 int len); 90 int len);
89extern char *mconsole_notify_socket(void); 91extern char *mconsole_notify_socket(void);
90extern void lock_notify(void); 92extern void lock_notify(void);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2cccfa5b8a..dd72d66cf0 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -9,6 +9,8 @@
9#include "uml-config.h" 9#include "uml-config.h"
10#include "asm/types.h" 10#include "asm/types.h"
11#include "../os/include/file.h" 11#include "../os/include/file.h"
12#include "sysdep/ptrace.h"
13#include "kern_util.h"
12 14
13#define OS_TYPE_FILE 1 15#define OS_TYPE_FILE 1
14#define OS_TYPE_DIR 2 16#define OS_TYPE_DIR 2
@@ -213,15 +215,24 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
213 int stack_order); 215 int stack_order);
214extern int helper_wait(int pid); 216extern int helper_wait(int pid);
215 217
216#endif 218/* umid.c */
217 219
218/* 220extern int umid_file_name(char *name, char *buf, int len);
219 * Overrides for Emacs so that we follow Linus's tabbing style. 221extern int set_umid(char *name);
220 * Emacs will notice this stuff at the end of the file and automatically 222extern char *get_umid(void);
221 * adjust the settings for this buffer only. This must remain at the end 223
222 * of the file. 224/* signal.c */
223 * --------------------------------------------------------------------------- 225extern void set_sigstack(void *sig_stack, int size);
224 * Local variables: 226extern void remove_sigstack(void);
225 * c-file-style: "linux" 227extern void set_handler(int sig, void (*handler)(int), int flags, ...);
226 * End: 228extern int change_sig(int signal, int on);
227 */ 229extern void block_signals(void);
230extern void unblock_signals(void);
231extern int get_signals(void);
232extern int set_signals(int enable);
233
234/* trap.c */
235extern void os_fill_handlinfo(struct kern_handlers h);
236extern void do_longjmp(void *p, int val);
237
238#endif
diff --git a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h
deleted file mode 100644
index b075e543d8..0000000000
--- a/arch/um/include/signal_user.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __SIGNAL_USER_H__
7#define __SIGNAL_USER_H__
8
9extern int signal_stack_size;
10
11extern int change_sig(int signal, int on);
12extern void set_sigstack(void *stack, int size);
13extern void set_handler(int sig, void (*handler)(int), int flags, ...);
14extern int set_signals(int enable);
15extern int get_signals(void);
16
17#endif
18
19/*
20 * Overrides for Emacs so that we follow Linus's tabbing style.
21 * Emacs will notice this stuff at the end of the file and automatically
22 * adjust the settings for this buffer only. This must remain at the end
23 * of the file.
24 * ---------------------------------------------------------------------------
25 * Local variables:
26 * c-file-style: "linux"
27 * End:
28 */
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/include/sysdep-i386/kernel-offsets.h
index 35db850575..82f96c5741 100644
--- a/arch/um/sys-i386/kernel-offsets.c
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,12 +1,9 @@
1#include <linux/config.h>
2#include <linux/stddef.h> 1#include <linux/stddef.h>
3#include <linux/sched.h> 2#include <linux/sched.h>
4#include <linux/time.h>
5#include <linux/elf.h> 3#include <linux/elf.h>
6#include <asm/page.h>
7 4
8#define DEFINE(sym, val) \ 5#define DEFINE(sym, val) \
9 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 6 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
10 7
11#define STR(x) #x 8#define STR(x) #x
12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) 9#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index bfcb104b84..5ce93abd0b 100644
--- a/arch/um/sys-x86_64/kernel-offsets.c
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -6,7 +6,7 @@
6#include <asm/page.h> 6#include <asm/page.h>
7 7
8#define DEFINE(sym, val) \ 8#define DEFINE(sym, val) \
9 asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 9 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
10 10
11#define DEFINE_STR1(x) #x 11#define DEFINE_STR1(x) #x
12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : ) 12#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index bb505e01d9..c1dbd77b07 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,12 +23,7 @@ struct cpu_task {
23 23
24extern struct cpu_task cpu_tasks[]; 24extern struct cpu_task cpu_tasks[];
25 25
26struct signal_info { 26extern void (*sig_info[])(int, union uml_pt_regs *);
27 void (*handler)(int, union uml_pt_regs *);
28 int is_irq;
29};
30
31extern struct signal_info sig_info[];
32 27
33extern unsigned long low_physmem; 28extern unsigned long low_physmem;
34extern unsigned long high_physmem; 29extern unsigned long high_physmem;
@@ -64,8 +59,6 @@ extern void setup_machinename(char *machine_out);
64extern void setup_hostinfo(void); 59extern void setup_hostinfo(void);
65extern void do_exec(int old_pid, int new_pid); 60extern void do_exec(int old_pid, int new_pid);
66extern void tracer_panic(char *msg, ...); 61extern void tracer_panic(char *msg, ...);
67extern char *get_umid(int only_if_set);
68extern void do_longjmp(void *p, int val);
69extern int detach(int pid, int sig); 62extern int detach(int pid, int sig);
70extern int attach(int pid); 63extern int attach(int pid);
71extern void kill_child_dead(int pid); 64extern void kill_child_dead(int pid);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 3de9d21e36..193cc2b744 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,9 @@ clean-files :=
9obj-y = config.o exec_kern.o exitcode.o \ 9obj-y = config.o exec_kern.o exitcode.o \
10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ 10 init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ 11 process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
12 signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ 12 signal_kern.o smp.o syscall_kern.o sysrq.o time.o \
13 time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ 13 time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \
14 umid.o user_util.o 14 user_util.o
15 15
16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o 16obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
17obj-$(CONFIG_GPROF) += gprof_syms.o 17obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
24 24
25user-objs-$(CONFIG_TTY_LOG) += tty_log.o 25user-objs-$(CONFIG_TTY_LOG) += tty_log.o
26 26
27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o 27USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o
28 28
29include arch/um/scripts/Makefile.rules 29include arch/um/scripts/Makefile.rules
30 30
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
index c13a64a288..91ea538e16 100644
--- a/arch/um/kernel/asm-offsets.c
+++ b/arch/um/kernel/asm-offsets.c
@@ -1 +1 @@
/* Dummy file to make kbuild happy - unused! */ #include "sysdep/kernel-offsets.h"
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3..0e32f5f4a8 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -15,7 +15,6 @@
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user.h" 16#include "user.h"
17#include "process.h" 17#include "process.h"
18#include "signal_user.h"
19#include "sigio.h" 18#include "sigio.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "os.h" 20#include "os.h"
@@ -29,7 +28,6 @@ struct irq_fd {
29 int pid; 28 int pid;
30 int events; 29 int events;
31 int current_events; 30 int current_events;
32 int freed;
33}; 31};
34 32
35static struct irq_fd *active_fds = NULL; 33static struct irq_fd *active_fds = NULL;
@@ -41,9 +39,11 @@ static int pollfds_size = 0;
41 39
42extern int io_count, intr_count; 40extern int io_count, intr_count;
43 41
42extern void free_irqs(void);
43
44void sigio_handler(int sig, union uml_pt_regs *regs) 44void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 45{
46 struct irq_fd *irq_fd, *next; 46 struct irq_fd *irq_fd;
47 int i, n; 47 int i, n;
48 48
49 if(smp_sigio_handler()) return; 49 if(smp_sigio_handler()) return;
@@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 66 irq_fd = irq_fd->next;
67 } 67 }
68 68
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 70 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 71 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 72 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 73 }
90 } 74 }
91 } 75 }
76
77 free_irqs();
92} 78}
93 79
94int activate_ipi(int fd, int pid) 80int activate_ipi(int fd, int pid)
@@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 122 .irq = irq,
137 .pid = pid, 123 .pid = pid,
138 .events = events, 124 .events = events,
139 .current_events = 0, 125 .current_events = 0 } );
140 .freed = 0 } );
141 126
142 /* Critical section - locked by a spinlock because this stuff can 127 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 128 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 298 return(irq);
314} 299}
315 300
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 301void reactivate_fd(int fd, int irqnum)
337{ 302{
338 struct irq_fd *irq; 303 struct irq_fd *irq;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 34b54a3e21..7f13b85d26 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -36,7 +36,6 @@
36#include "kern_util.h" 36#include "kern_util.h"
37#include "kern.h" 37#include "kern.h"
38#include "signal_kern.h" 38#include "signal_kern.h"
39#include "signal_user.h"
40#include "init.h" 39#include "init.h"
41#include "irq_user.h" 40#include "irq_user.h"
42#include "mem_user.h" 41#include "mem_user.h"
@@ -108,7 +107,7 @@ void set_current(void *t)
108{ 107{
109 struct task_struct *task = t; 108 struct task_struct *task = t;
110 109
111 cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) 110 cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
112 { external_pid(task), task }); 111 { external_pid(task), task });
113} 112}
114 113
@@ -324,10 +323,6 @@ int user_context(unsigned long sp)
324 return(stack != (unsigned long) current_thread); 323 return(stack != (unsigned long) current_thread);
325} 324}
326 325
327extern void remove_umid_dir(void);
328
329__uml_exitcall(remove_umid_dir);
330
331extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; 326extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
332 327
333void do_uml_exitcalls(void) 328void do_uml_exitcalls(void)
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index a637e885c5..6f1a3a2881 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -12,6 +12,8 @@
12#include "mode.h" 12#include "mode.h"
13#include "choose-mode.h" 13#include "choose-mode.h"
14 14
15void (*pm_power_off)(void);
16
15#ifdef CONFIG_SMP 17#ifdef CONFIG_SMP
16static void kill_idlers(int me) 18static void kill_idlers(int me)
17{ 19{
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9..62e5cfdf21 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
216 "err = %d\n", -n); 216 "err = %d\n", -n);
217 } 217 }
218 } 218 }
219
220 return 0;
219} 221}
220 222
221static int need_poll(int n) 223static int need_poll(int n)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 03618bd13d..7b0e0e81c1 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -22,7 +22,6 @@
22#include "asm/ucontext.h" 22#include "asm/ucontext.h"
23#include "kern_util.h" 23#include "kern_util.h"
24#include "signal_kern.h" 24#include "signal_kern.h"
25#include "signal_user.h"
26#include "kern.h" 25#include "kern.h"
27#include "frame_kern.h" 26#include "frame_kern.h"
28#include "sigcontext.h" 27#include "sigcontext.h"
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
deleted file mode 100644
index 62f457835f..0000000000
--- a/arch/um/kernel/signal_user.c
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <signal.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <sys/mman.h>
14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h"
17#include "signal_user.h"
18#include "signal_kern.h"
19#include "sysdep/sigcontext.h"
20#include "sigcontext.h"
21
22void set_sigstack(void *sig_stack, int size)
23{
24 stack_t stack = ((stack_t) { .ss_flags = 0,
25 .ss_sp = (__ptr_t) sig_stack,
26 .ss_size = size - sizeof(void *) });
27
28 if(sigaltstack(&stack, NULL) != 0)
29 panic("enabling signal stack failed, errno = %d\n", errno);
30}
31
32void set_handler(int sig, void (*handler)(int), int flags, ...)
33{
34 struct sigaction action;
35 va_list ap;
36 int mask;
37
38 va_start(ap, flags);
39 action.sa_handler = handler;
40 sigemptyset(&action.sa_mask);
41 while((mask = va_arg(ap, int)) != -1){
42 sigaddset(&action.sa_mask, mask);
43 }
44 va_end(ap);
45 action.sa_flags = flags;
46 action.sa_restorer = NULL;
47 if(sigaction(sig, &action, NULL) < 0)
48 panic("sigaction failed");
49}
50
51int change_sig(int signal, int on)
52{
53 sigset_t sigset, old;
54
55 sigemptyset(&sigset);
56 sigaddset(&sigset, signal);
57 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
58 return(!sigismember(&old, signal));
59}
60
61/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
62 * disable profiling; it's safe because the profiling code does not interact
63 * with the kernel code at all.*/
64
65static void change_signals(int type)
66{
67 sigset_t mask;
68
69 sigemptyset(&mask);
70 sigaddset(&mask, SIGVTALRM);
71 sigaddset(&mask, SIGALRM);
72 sigaddset(&mask, SIGIO);
73 if(sigprocmask(type, &mask, NULL) < 0)
74 panic("Failed to change signal mask - errno = %d", errno);
75}
76
77void block_signals(void)
78{
79 change_signals(SIG_BLOCK);
80}
81
82void unblock_signals(void)
83{
84 change_signals(SIG_UNBLOCK);
85}
86
87/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
88 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
89 * be able to profile all of UML, not just the non-critical sections. If
90 * profiling is not thread-safe, then that is not my problem. We can disable
91 * profiling when SMP is enabled in that case.
92 */
93#define SIGIO_BIT 0
94#define SIGVTALRM_BIT 1
95
96static int enable_mask(sigset_t *mask)
97{
98 int sigs;
99
100 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
101 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
102 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
103 return(sigs);
104}
105
106int get_signals(void)
107{
108 sigset_t mask;
109
110 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
111 panic("Failed to get signal mask");
112 return(enable_mask(&mask));
113}
114
115int set_signals(int enable)
116{
117 sigset_t mask;
118 int ret;
119
120 sigemptyset(&mask);
121 if(enable & (1 << SIGIO_BIT))
122 sigaddset(&mask, SIGIO);
123 if(enable & (1 << SIGVTALRM_BIT)){
124 sigaddset(&mask, SIGVTALRM);
125 sigaddset(&mask, SIGALRM);
126 }
127
128 /* This is safe - sigprocmask is guaranteed to copy locally the
129 * value of new_set, do his work and then, at the end, write to
130 * old_set.
131 */
132 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
133 panic("Failed to enable signals");
134 ret = enable_mask(&mask);
135 sigemptyset(&mask);
136 if((enable & (1 << SIGIO_BIT)) == 0)
137 sigaddset(&mask, SIGIO);
138 if((enable & (1 << SIGVTALRM_BIT)) == 0){
139 sigaddset(&mask, SIGVTALRM);
140 sigaddset(&mask, SIGALRM);
141 }
142 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
143 panic("Failed to block signals");
144
145 return(ret);
146}
147
148/*
149 * Overrides for Emacs so that we follow Linus's tabbing style.
150 * Emacs will notice this stuff at the end of the file and automatically
151 * adjust the settings for this buffer only. This must remain at the end
152 * of the file.
153 * ---------------------------------------------------------------------------
154 * Local variables:
155 * c-file-style: "linux"
156 * End:
157 */
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 8de471b59c..7a9fc16d71 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -4,7 +4,7 @@
4# 4#
5 5
6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ 6obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
7 syscall.o tlb.o trap_user.o uaccess.o 7 syscall.o tlb.o uaccess.o
8 8
9USER_OBJS := process.o clone.o 9USER_OBJS := process.o clone.o
10 10
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index daa2f85b68..01d489de39 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -22,7 +22,6 @@ extern int start_idle_thread(void *stack, void *switch_buf_ptr,
22extern int user_thread(unsigned long stack, int flags); 22extern int user_thread(unsigned long stack, int flags);
23extern void userspace(union uml_pt_regs *regs); 23extern void userspace(union uml_pt_regs *regs);
24extern void new_thread_proc(void *stack, void (*handler)(int sig)); 24extern void new_thread_proc(void *stack, void (*handler)(int sig));
25extern void remove_sigstack(void);
26extern void new_thread_handler(int sig); 25extern void new_thread_handler(int sig);
27extern void handle_syscall(union uml_pt_regs *regs); 26extern void handle_syscall(union uml_pt_regs *regs);
28extern int map(struct mm_id * mm_idp, unsigned long virt, 27extern int map(struct mm_id * mm_idp, unsigned long virt,
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 599d679bd4..3b3955d844 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -31,7 +31,6 @@
31#include "proc_mm.h" 31#include "proc_mm.h"
32#include "skas_ptrace.h" 32#include "skas_ptrace.h"
33#include "chan_user.h" 33#include "chan_user.h"
34#include "signal_user.h"
35#include "registers.h" 34#include "registers.h"
36#include "mem.h" 35#include "mem.h"
37#include "uml-config.h" 36#include "uml-config.h"
@@ -69,7 +68,7 @@ void wait_stub_done(int pid, int sig, char * fname)
69 68
70 if((n < 0) || !WIFSTOPPED(status) || 69 if((n < 0) || !WIFSTOPPED(status) ||
71 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 70 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
72 unsigned long regs[FRAME_SIZE]; 71 unsigned long regs[HOST_FRAME_SIZE];
73 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 72 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
74 printk("Failed to get registers from stub, " 73 printk("Failed to get registers from stub, "
75 "errno = %d\n", errno); 74 "errno = %d\n", errno);
@@ -77,7 +76,7 @@ void wait_stub_done(int pid, int sig, char * fname)
77 int i; 76 int i;
78 77
79 printk("Stub registers -\n"); 78 printk("Stub registers -\n");
80 for(i = 0; i < FRAME_SIZE; i++) 79 for(i = 0; i < HOST_FRAME_SIZE; i++)
81 printk("\t%d - %lx\n", i, regs[i]); 80 printk("\t%d - %lx\n", i, regs[i]);
82 } 81 }
83 panic("%s : failed to wait for SIGUSR1/SIGTRAP, " 82 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
@@ -514,16 +513,6 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
514 siglongjmp(**switch_buf, 1); 513 siglongjmp(**switch_buf, 1);
515} 514}
516 515
517void remove_sigstack(void)
518{
519 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
520 .ss_sp = NULL,
521 .ss_size = 0 });
522
523 if(sigaltstack(&stack, NULL) != 0)
524 panic("disabling signal stack failed, errno = %d\n", errno);
525}
526
527void initial_thread_cb_skas(void (*proc)(void *), void *arg) 516void initial_thread_cb_skas(void (*proc)(void *), void *arg)
528{ 517{
529 sigjmp_buf here; 518 sigjmp_buf here;
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 9c99025396..dc41c6dc2f 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -14,7 +14,6 @@
14#include "asm/atomic.h" 14#include "asm/atomic.h"
15#include "kern_util.h" 15#include "kern_util.h"
16#include "time_user.h" 16#include "time_user.h"
17#include "signal_user.h"
18#include "skas.h" 17#include "skas.h"
19#include "os.h" 18#include "os.h"
20#include "user_util.h" 19#include "user_util.h"
@@ -119,7 +118,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
119 handler = new_thread_handler; 118 handler = new_thread_handler;
120 } 119 }
121 120
122 new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, 121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
123 &p->thread.mode.skas.fork_buf, handler); 122 &p->thread.mode.skas.fork_buf, handler);
124 return(0); 123 return(0);
125} 124}
@@ -186,7 +185,7 @@ int start_uml_skas(void)
186 185
187 init_task.thread.request.u.thread.proc = start_kernel_proc; 186 init_task.thread.request.u.thread.proc = start_kernel_proc;
188 init_task.thread.request.u.thread.arg = NULL; 187 init_task.thread.request.u.thread.arg = NULL;
189 return(start_idle_thread(init_task.thread_info, 188 return(start_idle_thread(task_stack_page(&init_task),
190 &init_task.thread.mode.skas.switch_buf, 189 &init_task.thread.mode.skas.switch_buf,
191 &init_task.thread.mode.skas.fork_buf)); 190 &init_task.thread.mode.skas.fork_buf));
192} 191}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40b611e3d..8fa2ae7f30 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -14,9 +14,9 @@
14#include "kern_util.h" 14#include "kern_util.h"
15#include "user.h" 15#include "user.h"
16#include "process.h" 16#include "process.h"
17#include "signal_user.h"
18#include "time_user.h" 17#include "time_user.h"
19#include "kern_constants.h" 18#include "kern_constants.h"
19#include "os.h"
20 20
21/* XXX This really needs to be declared and initialized in a kernel file since 21/* XXX This really needs to be declared and initialized in a kernel file since
22 * it's in <linux/time.h> 22 * it's in <linux/time.h>
@@ -99,7 +99,8 @@ void uml_idle_timer(void)
99 set_interval(ITIMER_REAL); 99 set_interval(ITIMER_REAL);
100} 100}
101 101
102extern int do_posix_clock_monotonic_gettime(struct timespec *tp); 102extern void ktime_get_ts(struct timespec *ts);
103#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
103 104
104void time_init(void) 105void time_init(void)
105{ 106{
@@ -114,8 +115,8 @@ void time_init(void)
114 wall_to_monotonic.tv_nsec = -now.tv_nsec; 115 wall_to_monotonic.tv_nsec = -now.tv_nsec;
115} 116}
116 117
117/* Declared in linux/time.h, which can't be included here */ 118/* Defined in linux/ktimer.h, which can't be included here */
118extern void clock_was_set(void); 119#define clock_was_set() do { } while (0)
119 120
120void do_gettimeofday(struct timeval *tv) 121void do_gettimeofday(struct timeval *tv)
121{ 122{
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 0d4c10a736..d56046c2ab 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -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 */
@@ -26,9 +26,13 @@
26#include "mconsole_kern.h" 26#include "mconsole_kern.h"
27#include "mem.h" 27#include "mem.h"
28#include "mem_kern.h" 28#include "mem_kern.h"
29#include "sysdep/sigcontext.h"
30#include "sysdep/ptrace.h"
31#include "os.h"
29#ifdef CONFIG_MODE_SKAS 32#ifdef CONFIG_MODE_SKAS
30#include "skas.h" 33#include "skas.h"
31#endif 34#endif
35#include "os.h"
32 36
33/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ 37/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
34int handle_page_fault(unsigned long address, unsigned long ip, 38int handle_page_fault(unsigned long address, unsigned long ip,
@@ -125,6 +129,25 @@ out_of_memory:
125 goto out; 129 goto out;
126} 130}
127 131
132void segv_handler(int sig, union uml_pt_regs *regs)
133{
134 struct faultinfo * fi = UPT_FAULTINFO(regs);
135
136 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
137 bad_segv(*fi, UPT_IP(regs));
138 return;
139 }
140 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
141}
142
143struct kern_handlers handlinfo_kern = {
144 .relay_signal = relay_signal,
145 .winch = winch,
146 .bus_handler = relay_signal,
147 .page_fault = segv_handler,
148 .sigio_handler = sigio_handler,
149 .timer_handler = timer_handler
150};
128/* 151/*
129 * We give a *copy* of the faultinfo in the regs to segv. 152 * We give a *copy* of the faultinfo in the regs to segv.
130 * This must be done, since nesting SEGVs could overwrite 153 * This must be done, since nesting SEGVs could overwrite
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
deleted file mode 100644
index e9ccd6b8d3..0000000000
--- a/arch/um/kernel/trap_user.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <errno.h>
8#include <setjmp.h>
9#include <signal.h>
10#include <sys/time.h>
11#include <sys/wait.h>
12#include <asm/page.h>
13#include <asm/unistd.h>
14#include <asm/ptrace.h>
15#include "init.h"
16#include "sysdep/ptrace.h"
17#include "sigcontext.h"
18#include "sysdep/sigcontext.h"
19#include "irq_user.h"
20#include "signal_user.h"
21#include "time_user.h"
22#include "task.h"
23#include "mode.h"
24#include "choose-mode.h"
25#include "kern_util.h"
26#include "user_util.h"
27#include "os.h"
28
29void kill_child_dead(int pid)
30{
31 kill(pid, SIGKILL);
32 kill(pid, SIGCONT);
33 do {
34 int n;
35 CATCH_EINTR(n = waitpid(pid, NULL, 0));
36 if (n > 0)
37 kill(pid, SIGCONT);
38 else
39 break;
40 } while(1);
41}
42
43void segv_handler(int sig, union uml_pt_regs *regs)
44{
45 struct faultinfo * fi = UPT_FAULTINFO(regs);
46
47 if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
48 bad_segv(*fi, UPT_IP(regs));
49 return;
50 }
51 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
52}
53
54void usr2_handler(int sig, union uml_pt_regs *regs)
55{
56 CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
57}
58
59struct signal_info sig_info[] = {
60 [ SIGTRAP ] { .handler = relay_signal,
61 .is_irq = 0 },
62 [ SIGFPE ] { .handler = relay_signal,
63 .is_irq = 0 },
64 [ SIGILL ] { .handler = relay_signal,
65 .is_irq = 0 },
66 [ SIGWINCH ] { .handler = winch,
67 .is_irq = 1 },
68 [ SIGBUS ] { .handler = bus_handler,
69 .is_irq = 0 },
70 [ SIGSEGV] { .handler = segv_handler,
71 .is_irq = 0 },
72 [ SIGIO ] { .handler = sigio_handler,
73 .is_irq = 1 },
74 [ SIGVTALRM ] { .handler = timer_handler,
75 .is_irq = 1 },
76 [ SIGALRM ] { .handler = timer_handler,
77 .is_irq = 1 },
78 [ SIGUSR2 ] { .handler = usr2_handler,
79 .is_irq = 0 },
80};
81
82void do_longjmp(void *b, int val)
83{
84 sigjmp_buf *buf = b;
85
86 siglongjmp(*buf, val);
87}
88
89/*
90 * Overrides for Emacs so that we follow Linus's tabbing style.
91 * Emacs will notice this stuff at the end of the file and automatically
92 * adjust the settings for this buffer only. This must remain at the end
93 * of the file.
94 * ---------------------------------------------------------------------------
95 * Local variables:
96 * c-file-style: "linux"
97 * End:
98 */
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 065b504a65..8f40e48387 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -14,7 +14,6 @@
14#include "kern_util.h" 14#include "kern_util.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "time_user.h" 16#include "time_user.h"
17#include "signal_user.h"
18#include "mem_user.h" 17#include "mem_user.h"
19#include "os.h" 18#include "os.h"
20#include "tlb.h" 19#include "tlb.h"
@@ -40,7 +39,7 @@ void flush_thread_tt(void)
40 do_exit(SIGKILL); 39 do_exit(SIGKILL);
41 } 40 }
42 41
43 new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); 42 new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
44 if(new_pid < 0){ 43 if(new_pid < 0){
45 printk(KERN_ERR 44 printk(KERN_ERR
46 "flush_thread : new thread failed, errno = %d\n", 45 "flush_thread : new thread failed, errno = %d\n",
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index cfaa373a6e..62535303aa 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -13,7 +13,6 @@
13#include "asm/ptrace.h" 13#include "asm/ptrace.h"
14#include "asm/tlbflush.h" 14#include "asm/tlbflush.h"
15#include "irq_user.h" 15#include "irq_user.h"
16#include "signal_user.h"
17#include "kern_util.h" 16#include "kern_util.h"
18#include "user_util.h" 17#include "user_util.h"
19#include "os.h" 18#include "os.h"
@@ -37,7 +36,7 @@ void switch_to_tt(void *prev, void *next)
37 from = prev; 36 from = prev;
38 to = next; 37 to = next;
39 38
40 cpu = from->thread_info->cpu; 39 cpu = task_thread_info(from)->cpu;
41 if(cpu == 0) 40 if(cpu == 0)
42 forward_interrupts(to->thread.mode.tt.extern_pid); 41 forward_interrupts(to->thread.mode.tt.extern_pid);
43#ifdef CONFIG_SMP 42#ifdef CONFIG_SMP
@@ -254,7 +253,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
254 253
255 clone_flags &= CLONE_VM; 254 clone_flags &= CLONE_VM;
256 p->thread.temp_stack = stack; 255 p->thread.temp_stack = stack;
257 new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); 256 new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
258 if(new_pid < 0){ 257 if(new_pid < 0){
259 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 258 printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
260 -new_pid); 259 -new_pid);
@@ -344,7 +343,7 @@ int do_proc_op(void *t, int proc_id)
344 pid = thread->request.u.exec.pid; 343 pid = thread->request.u.exec.pid;
345 do_exec(thread->mode.tt.extern_pid, pid); 344 do_exec(thread->mode.tt.extern_pid, pid);
346 thread->mode.tt.extern_pid = pid; 345 thread->mode.tt.extern_pid = pid;
347 cpu_tasks[task->thread_info->cpu].pid = pid; 346 cpu_tasks[task_thread_info(task)->cpu].pid = pid;
348 break; 347 break;
349 case OP_FORK: 348 case OP_FORK:
350 attach_process(thread->request.u.fork.pid); 349 attach_process(thread->request.u.fork.pid);
@@ -426,7 +425,7 @@ int start_uml_tt(void)
426 int pages; 425 int pages;
427 426
428 pages = (1 << CONFIG_KERNEL_STACK_ORDER); 427 pages = (1 << CONFIG_KERNEL_STACK_ORDER);
429 sp = (void *) ((unsigned long) init_task.thread_info) + 428 sp = task_stack_page(&init_task) +
430 pages * PAGE_SIZE - sizeof(unsigned long); 429 pages * PAGE_SIZE - sizeof(unsigned long);
431 return(tracer(start_kernel_proc, sp)); 430 return(tracer(start_kernel_proc, sp));
432} 431}
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index d11e7399d7..71daae24e4 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
19#include "sigcontext.h" 19#include "sigcontext.h"
20#include "sysdep/sigcontext.h" 20#include "sysdep/sigcontext.h"
21#include "os.h" 21#include "os.h"
22#include "signal_user.h"
23#include "user_util.h" 22#include "user_util.h"
24#include "mem_user.h" 23#include "mem_user.h"
25#include "process.h" 24#include "process.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index fc108615be..a414c529fb 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_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 */
@@ -8,18 +8,18 @@
8#include <signal.h> 8#include <signal.h>
9#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
10#include "sysdep/sigcontext.h" 10#include "sysdep/sigcontext.h"
11#include "signal_user.h"
12#include "user_util.h" 11#include "user_util.h"
13#include "kern_util.h" 12#include "kern_util.h"
14#include "task.h" 13#include "task.h"
15#include "tt.h" 14#include "tt.h"
15#include "os.h"
16 16
17void sig_handler_common_tt(int sig, void *sc_ptr) 17void sig_handler_common_tt(int sig, void *sc_ptr)
18{ 18{
19 struct sigcontext *sc = sc_ptr; 19 struct sigcontext *sc = sc_ptr;
20 struct tt_regs save_regs, *r; 20 struct tt_regs save_regs, *r;
21 struct signal_info *info;
22 int save_errno = errno, is_user; 21 int save_errno = errno, is_user;
22 void (*handler)(int, union uml_pt_regs *);
23 23
24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV 24 /* This is done because to allow SIGSEGV to be delivered inside a SEGV
25 * handler. This can happen in copy_user, and if SEGV is disabled, 25 * handler. This can happen in copy_user, and if SEGV is disabled,
@@ -40,10 +40,14 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
40 if(sig != SIGUSR2) 40 if(sig != SIGUSR2)
41 r->syscall = -1; 41 r->syscall = -1;
42 42
43 info = &sig_info[sig]; 43 handler = sig_info[sig];
44 if(!info->is_irq) unblock_signals(); 44
45 /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
46 if (sig != SIGIO && sig != SIGWINCH &&
47 sig != SIGVTALRM && sig != SIGALRM)
48 unblock_signals();
45 49
46 (*info->handler)(sig, (union uml_pt_regs *) r); 50 handler(sig, (union uml_pt_regs *) r);
47 51
48 if(is_user){ 52 if(is_user){
49 interrupt_end(); 53 interrupt_end();
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 142a949391..e2d3ca445e 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -146,8 +146,8 @@ void set_cmdline(char *cmd)
146 146
147 if(CHOOSE_MODE(honeypot, 0)) return; 147 if(CHOOSE_MODE(honeypot, 0)) return;
148 148
149 umid = get_umid(1); 149 umid = get_umid();
150 if(umid != NULL){ 150 if(*umid != '\0'){
151 snprintf(argv1_begin, 151 snprintf(argv1_begin,
152 (argv1_end - argv1_begin) * sizeof(*ptr), 152 (argv1_end - argv1_begin) * sizeof(*ptr),
153 "(%s) ", umid); 153 "(%s) ", umid);
@@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add)
243 return(0); 243 return(0);
244} 244}
245 245
246#else
247
248#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
249
250#endif 246#endif
251#endif 247#endif
252#endif 248#endif
@@ -363,6 +359,11 @@ int linux_main(int argc, char **argv)
363 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 359 uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
364 &host_task_size, &task_size); 360 &host_task_size, &task_size);
365 361
362 /*
363 * Setting up handlers to 'sig_info' struct
364 */
365 os_fill_handlinfo(handlinfo_kern);
366
366 brk_start = (unsigned long) sbrk(0); 367 brk_start = (unsigned long) sbrk(0);
367 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 368 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
368 /* Increase physical memory size for exec-shield users 369 /* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 0b21d59ba0..4eaee823bf 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -3,61 +3,30 @@
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <stdio.h> 6#include "asm/errno.h"
7#include <unistd.h>
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <dirent.h>
12#include <signal.h>
13#include <sys/stat.h>
14#include <sys/param.h>
15#include "user.h"
16#include "umid.h"
17#include "init.h" 7#include "init.h"
18#include "os.h" 8#include "os.h"
19#include "user_util.h" 9#include "kern.h"
20#include "choose-mode.h" 10#include "linux/kernel.h"
21 11
22#define UMID_LEN 64 12/* Changed by set_umid_arg */
23#define UML_DIR "~/.uml/"
24
25/* Changed by set_umid and make_umid, which are run early in boot */
26static char umid[UMID_LEN] = { 0 };
27
28/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
29static char *uml_dir = UML_DIR;
30
31/* Changed by set_umid */
32static int umid_is_random = 1;
33static int umid_inited = 0; 13static int umid_inited = 0;
34/* Have we created the files? Should we remove them? */
35static int umid_owned = 0;
36 14
37static int make_umid(int (*printer)(const char *fmt, ...)); 15static int __init set_umid_arg(char *name, int *add)
38
39static int __init set_umid(char *name, int is_random,
40 int (*printer)(const char *fmt, ...))
41{ 16{
42 if(umid_inited){ 17 int err;
43 (*printer)("Unique machine name can't be set twice\n");
44 return(-1);
45 }
46 18
47 if(strlen(name) > UMID_LEN - 1) 19 if(umid_inited)
48 (*printer)("Unique machine name is being truncated to %d " 20 return 0;
49 "characters\n", UMID_LEN);
50 strlcpy(umid, name, sizeof(umid));
51 21
52 umid_is_random = is_random;
53 umid_inited = 1;
54 return 0;
55}
56
57static int __init set_umid_arg(char *name, int *add)
58{
59 *add = 0; 22 *add = 0;
60 return(set_umid(name, 0, printf)); 23 err = set_umid(name);
24 if(err == -EEXIST)
25 printf("umid '%s' already in use\n", name);
26 else if(!err)
27 umid_inited = 1;
28
29 return 0;
61} 30}
62 31
63__uml_setup("umid=", set_umid_arg, 32__uml_setup("umid=", set_umid_arg,
@@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg,
66" is used for naming the pid file and management console socket.\n\n" 35" is used for naming the pid file and management console socket.\n\n"
67); 36);
68 37
69int __init umid_file_name(char *name, char *buf, int len)
70{
71 int n;
72
73 if(!umid_inited && make_umid(printk)) return(-1);
74
75 n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
76 if(n > len){
77 printk("umid_file_name : buffer too short\n");
78 return(-1);
79 }
80
81 sprintf(buf, "%s%s/%s", uml_dir, umid, name);
82 return(0);
83}
84
85extern int tracing_pid;
86
87static void __init create_pid_file(void)
88{
89 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
90 char pid[sizeof("nnnnn\0")];
91 int fd, n;
92
93 if(umid_file_name("pid", file, sizeof(file)))
94 return;
95
96 fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
97 0644);
98 if(fd < 0){
99 printf("Open of machine pid file \"%s\" failed: %s\n",
100 file, strerror(-fd));
101 return;
102 }
103
104 sprintf(pid, "%d\n", os_getpid());
105 n = os_write_file(fd, pid, strlen(pid));
106 if(n != strlen(pid))
107 printf("Write of pid file failed - err = %d\n", -n);
108 os_close_file(fd);
109}
110
111static int actually_do_remove(char *dir)
112{
113 DIR *directory;
114 struct dirent *ent;
115 int len;
116 char file[256];
117
118 directory = opendir(dir);
119 if(directory == NULL){
120 printk("actually_do_remove : couldn't open directory '%s', "
121 "errno = %d\n", dir, errno);
122 return(1);
123 }
124 while((ent = readdir(directory)) != NULL){
125 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
126 continue;
127 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
128 if(len > sizeof(file)){
129 printk("Not deleting '%s' from '%s' - name too long\n",
130 ent->d_name, dir);
131 continue;
132 }
133 sprintf(file, "%s/%s", dir, ent->d_name);
134 if(unlink(file) < 0){
135 printk("actually_do_remove : couldn't remove '%s' "
136 "from '%s', errno = %d\n", ent->d_name, dir,
137 errno);
138 return(1);
139 }
140 }
141 if(rmdir(dir) < 0){
142 printk("actually_do_remove : couldn't rmdir '%s', "
143 "errno = %d\n", dir, errno);
144 return(1);
145 }
146 return(0);
147}
148
149void remove_umid_dir(void)
150{
151 char dir[strlen(uml_dir) + UMID_LEN + 1];
152 if (!umid_owned)
153 return;
154
155 sprintf(dir, "%s%s", uml_dir, umid);
156 actually_do_remove(dir);
157}
158
159char *get_umid(int only_if_set)
160{
161 if(only_if_set && umid_is_random)
162 return NULL;
163 return umid;
164}
165
166static int not_dead_yet(char *dir)
167{
168 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
169 char pid[sizeof("nnnnn\0")], *end;
170 int dead, fd, p, n;
171
172 sprintf(file, "%s/pid", dir);
173 dead = 0;
174 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
175 if(fd < 0){
176 if(fd != -ENOENT){
177 printk("not_dead_yet : couldn't open pid file '%s', "
178 "err = %d\n", file, -fd);
179 return(1);
180 }
181 dead = 1;
182 }
183 if(fd > 0){
184 n = os_read_file(fd, pid, sizeof(pid));
185 if(n < 0){
186 printk("not_dead_yet : couldn't read pid file '%s', "
187 "err = %d\n", file, -n);
188 return(1);
189 }
190 p = strtoul(pid, &end, 0);
191 if(end == pid){
192 printk("not_dead_yet : couldn't parse pid file '%s', "
193 "errno = %d\n", file, errno);
194 dead = 1;
195 }
196 if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
197 (p == CHOOSE_MODE(tracing_pid, os_getpid())))
198 dead = 1;
199 }
200 if(!dead)
201 return(1);
202 return(actually_do_remove(dir));
203}
204
205static int __init set_uml_dir(char *name, int *add)
206{
207 if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
208 uml_dir = malloc(strlen(name) + 2);
209 if(uml_dir == NULL){
210 printf("Failed to malloc uml_dir - error = %d\n",
211 errno);
212 uml_dir = name;
213 /* Return 0 here because do_initcalls doesn't look at
214 * the return value.
215 */
216 return(0);
217 }
218 sprintf(uml_dir, "%s/", name);
219 }
220 else uml_dir = name;
221 return(0);
222}
223
224static int __init make_uml_dir(void)
225{
226 char dir[MAXPATHLEN + 1] = { '\0' };
227 int len;
228
229 if(*uml_dir == '~'){
230 char *home = getenv("HOME");
231
232 if(home == NULL){
233 printf("make_uml_dir : no value in environment for "
234 "$HOME\n");
235 exit(1);
236 }
237 strlcpy(dir, home, sizeof(dir));
238 uml_dir++;
239 }
240 strlcat(dir, uml_dir, sizeof(dir));
241 len = strlen(dir);
242 if (len > 0 && dir[len - 1] != '/')
243 strlcat(dir, "/", sizeof(dir));
244
245 uml_dir = malloc(strlen(dir) + 1);
246 if (uml_dir == NULL) {
247 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
248 exit(1);
249 }
250 strcpy(uml_dir, dir);
251
252 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
253 printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno));
254 return(-1);
255 }
256 return 0;
257}
258
259static int __init make_umid(int (*printer)(const char *fmt, ...))
260{
261 int fd, err;
262 char tmp[strlen(uml_dir) + UMID_LEN + 1];
263
264 strlcpy(tmp, uml_dir, sizeof(tmp));
265
266 if(!umid_inited){
267 strcat(tmp, "XXXXXX");
268 fd = mkstemp(tmp);
269 if(fd < 0){
270 (*printer)("make_umid - mkstemp(%s) failed: %s\n",
271 tmp,strerror(errno));
272 return(1);
273 }
274
275 os_close_file(fd);
276 /* There's a nice tiny little race between this unlink and
277 * the mkdir below. It'd be nice if there were a mkstemp
278 * for directories.
279 */
280 unlink(tmp);
281 set_umid(&tmp[strlen(uml_dir)], 1, printer);
282 }
283
284 sprintf(tmp, "%s%s", uml_dir, umid);
285
286 err = mkdir(tmp, 0777);
287 if(err < 0){
288 if(errno == EEXIST){
289 if(not_dead_yet(tmp)){
290 (*printer)("umid '%s' is in use\n", umid);
291 umid_owned = 0;
292 return(-1);
293 }
294 err = mkdir(tmp, 0777);
295 }
296 }
297 if(err < 0){
298 (*printer)("Failed to create %s - errno = %d\n", umid, errno);
299 return(-1);
300 }
301
302 umid_owned = 1;
303 return 0;
304}
305
306__uml_setup("uml_dir=", set_uml_dir,
307"uml_dir=<directory>\n"
308" The location to place the pid and umid files.\n\n"
309);
310
311static int __init make_umid_setup(void)
312{
313 /* one function with the ordering we need ... */
314 make_uml_dir();
315 make_umid(printf);
316 create_pid_file();
317 return 0;
318}
319__uml_postsetup(make_umid_setup);
320
321/*
322 * Overrides for Emacs so that we follow Linus's tabbing style.
323 * Emacs will notice this stuff at the end of the file and automatically
324 * adjust the settings for this buffer only. This must remain at the end
325 * of the file.
326 * ---------------------------------------------------------------------------
327 * Local variables:
328 * c-file-style: "linux"
329 * End:
330 */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b83ac8e21c..40c7d6b1df 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,11 +4,13 @@
4# 4#
5 5
6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 6obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
7 start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ 7 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
8 sys-$(SUBARCH)/ 8 drivers/ sys-$(SUBARCH)/
9
10obj-$(CONFIG_MODE_SKAS) += skas/
9 11
10USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ 12USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
11 start_up.o time.o tt.o tty.o uaccess.o 13 start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o
12 14
13elf_aux.o: $(ARCH_DIR)/kernel-offsets.h 15elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
14CFLAGS_elf_aux.o += -I$(objtree)/arch/um 16CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index ffa759addd..f897140cc4 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -16,12 +16,12 @@
16#include "mode.h" 16#include "mode.h"
17 17
18struct aio_thread_req { 18struct aio_thread_req {
19 enum aio_type type; 19 enum aio_type type;
20 int io_fd; 20 int io_fd;
21 unsigned long long offset; 21 unsigned long long offset;
22 char *buf; 22 char *buf;
23 int len; 23 int len;
24 struct aio_context *aio; 24 struct aio_context *aio;
25}; 25};
26 26
27static int aio_req_fd_r = -1; 27static int aio_req_fd_r = -1;
@@ -38,18 +38,18 @@ static int aio_req_fd_w = -1;
38 38
39static long io_setup(int n, aio_context_t *ctxp) 39static long io_setup(int n, aio_context_t *ctxp)
40{ 40{
41 return syscall(__NR_io_setup, n, ctxp); 41 return syscall(__NR_io_setup, n, ctxp);
42} 42}
43 43
44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) 44static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
45{ 45{
46 return syscall(__NR_io_submit, ctx, nr, iocbpp); 46 return syscall(__NR_io_submit, ctx, nr, iocbpp);
47} 47}
48 48
49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, 49static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
50 struct io_event *events, struct timespec *timeout) 50 struct io_event *events, struct timespec *timeout)
51{ 51{
52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); 52 return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
53} 53}
54 54
55#endif 55#endif
@@ -66,243 +66,245 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
66 */ 66 */
67 67
68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, 68static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
69 int len, unsigned long long offset, struct aio_context *aio) 69 int len, unsigned long long offset, struct aio_context *aio)
70{ 70{
71 struct iocb iocb, *iocbp = &iocb; 71 struct iocb iocb, *iocbp = &iocb;
72 char c; 72 char c;
73 int err; 73 int err;
74 74
75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio, 75 iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
76 .aio_reqprio = 0, 76 .aio_reqprio = 0,
77 .aio_fildes = fd, 77 .aio_fildes = fd,
78 .aio_buf = (unsigned long) buf, 78 .aio_buf = (unsigned long) buf,
79 .aio_nbytes = len, 79 .aio_nbytes = len,
80 .aio_offset = offset, 80 .aio_offset = offset,
81 .aio_reserved1 = 0, 81 .aio_reserved1 = 0,
82 .aio_reserved2 = 0, 82 .aio_reserved2 = 0,
83 .aio_reserved3 = 0 }); 83 .aio_reserved3 = 0 });
84 84
85 switch(type){ 85 switch(type){
86 case AIO_READ: 86 case AIO_READ:
87 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 87 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
88 err = io_submit(ctx, 1, &iocbp); 88 err = io_submit(ctx, 1, &iocbp);
89 break; 89 break;
90 case AIO_WRITE: 90 case AIO_WRITE:
91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE; 91 iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
92 err = io_submit(ctx, 1, &iocbp); 92 err = io_submit(ctx, 1, &iocbp);
93 break; 93 break;
94 case AIO_MMAP: 94 case AIO_MMAP:
95 iocb.aio_lio_opcode = IOCB_CMD_PREAD; 95 iocb.aio_lio_opcode = IOCB_CMD_PREAD;
96 iocb.aio_buf = (unsigned long) &c; 96 iocb.aio_buf = (unsigned long) &c;
97 iocb.aio_nbytes = sizeof(c); 97 iocb.aio_nbytes = sizeof(c);
98 err = io_submit(ctx, 1, &iocbp); 98 err = io_submit(ctx, 1, &iocbp);
99 break; 99 break;
100 default: 100 default:
101 printk("Bogus op in do_aio - %d\n", type); 101 printk("Bogus op in do_aio - %d\n", type);
102 err = -EINVAL; 102 err = -EINVAL;
103 break; 103 break;
104 } 104 }
105 105
106 if(err > 0) 106 if(err > 0)
107 err = 0; 107 err = 0;
108 else 108 else
109 err = -errno; 109 err = -errno;
110 110
111 return err; 111 return err;
112} 112}
113 113
114static aio_context_t ctx = 0; 114static aio_context_t ctx = 0;
115 115
116static int aio_thread(void *arg) 116static int aio_thread(void *arg)
117{ 117{
118 struct aio_thread_reply reply; 118 struct aio_thread_reply reply;
119 struct io_event event; 119 struct io_event event;
120 int err, n, reply_fd; 120 int err, n, reply_fd;
121 121
122 signal(SIGWINCH, SIG_IGN); 122 signal(SIGWINCH, SIG_IGN);
123 123
124 while(1){ 124 while(1){
125 n = io_getevents(ctx, 1, 1, &event, NULL); 125 n = io_getevents(ctx, 1, 1, &event, NULL);
126 if(n < 0){ 126 if(n < 0){
127 if(errno == EINTR) 127 if(errno == EINTR)
128 continue; 128 continue;
129 printk("aio_thread - io_getevents failed, " 129 printk("aio_thread - io_getevents failed, "
130 "errno = %d\n", errno); 130 "errno = %d\n", errno);
131 } 131 }
132 else { 132 else {
133 reply = ((struct aio_thread_reply) 133 reply = ((struct aio_thread_reply)
134 { .data = (void *) (long) event.data, 134 { .data = (void *) (long) event.data,
135 .err = event.res }); 135 .err = event.res });
136 reply_fd = ((struct aio_context *) reply.data)->reply_fd; 136 reply_fd = ((struct aio_context *) reply.data)->reply_fd;
137 err = os_write_file(reply_fd, &reply, sizeof(reply)); 137 err = os_write_file(reply_fd, &reply, sizeof(reply));
138 if(err != sizeof(reply)) 138 if(err != sizeof(reply))
139 printk("aio_thread - write failed, fd = %d, " 139 printk("aio_thread - write failed, fd = %d, "
140 "err = %d\n", aio_req_fd_r, -err); 140 "err = %d\n", aio_req_fd_r, -err);
141 } 141 }
142 } 142 }
143 return 0; 143 return 0;
144} 144}
145 145
146#endif 146#endif
147 147
148static int do_not_aio(struct aio_thread_req *req) 148static int do_not_aio(struct aio_thread_req *req)
149{ 149{
150 char c; 150 char c;
151 int err; 151 int err;
152 152
153 switch(req->type){ 153 switch(req->type){
154 case AIO_READ: 154 case AIO_READ:
155 err = os_seek_file(req->io_fd, req->offset); 155 err = os_seek_file(req->io_fd, req->offset);
156 if(err) 156 if(err)
157 goto out; 157 goto out;
158 158
159 err = os_read_file(req->io_fd, req->buf, req->len); 159 err = os_read_file(req->io_fd, req->buf, req->len);
160 break; 160 break;
161 case AIO_WRITE: 161 case AIO_WRITE:
162 err = os_seek_file(req->io_fd, req->offset); 162 err = os_seek_file(req->io_fd, req->offset);
163 if(err) 163 if(err)
164 goto out; 164 goto out;
165 165
166 err = os_write_file(req->io_fd, req->buf, req->len); 166 err = os_write_file(req->io_fd, req->buf, req->len);
167 break; 167 break;
168 case AIO_MMAP: 168 case AIO_MMAP:
169 err = os_seek_file(req->io_fd, req->offset); 169 err = os_seek_file(req->io_fd, req->offset);
170 if(err) 170 if(err)
171 goto out; 171 goto out;
172 172
173 err = os_read_file(req->io_fd, &c, sizeof(c)); 173 err = os_read_file(req->io_fd, &c, sizeof(c));
174 break; 174 break;
175 default: 175 default:
176 printk("do_not_aio - bad request type : %d\n", req->type); 176 printk("do_not_aio - bad request type : %d\n", req->type);
177 err = -EINVAL; 177 err = -EINVAL;
178 break; 178 break;
179 } 179 }
180 180
181 out: 181out:
182 return err; 182 return err;
183} 183}
184 184
185static int not_aio_thread(void *arg) 185static int not_aio_thread(void *arg)
186{ 186{
187 struct aio_thread_req req; 187 struct aio_thread_req req;
188 struct aio_thread_reply reply; 188 struct aio_thread_reply reply;
189 int err; 189 int err;
190 190
191 signal(SIGWINCH, SIG_IGN); 191 signal(SIGWINCH, SIG_IGN);
192 while(1){ 192 while(1){
193 err = os_read_file(aio_req_fd_r, &req, sizeof(req)); 193 err = os_read_file(aio_req_fd_r, &req, sizeof(req));
194 if(err != sizeof(req)){ 194 if(err != sizeof(req)){
195 if(err < 0) 195 if(err < 0)
196 printk("not_aio_thread - read failed, " 196 printk("not_aio_thread - read failed, "
197 "fd = %d, err = %d\n", aio_req_fd_r, 197 "fd = %d, err = %d\n", aio_req_fd_r,
198 -err); 198 -err);
199 else { 199 else {
200 printk("not_aio_thread - short read, fd = %d, " 200 printk("not_aio_thread - short read, fd = %d, "
201 "length = %d\n", aio_req_fd_r, err); 201 "length = %d\n", aio_req_fd_r, err);
202 } 202 }
203 continue; 203 continue;
204 } 204 }
205 err = do_not_aio(&req); 205 err = do_not_aio(&req);
206 reply = ((struct aio_thread_reply) { .data = req.aio, 206 reply = ((struct aio_thread_reply) { .data = req.aio,
207 .err = err }); 207 .err = err });
208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); 208 err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply));
209 if(err != sizeof(reply)) 209 if(err != sizeof(reply))
210 printk("not_aio_thread - write failed, fd = %d, " 210 printk("not_aio_thread - write failed, fd = %d, "
211 "err = %d\n", aio_req_fd_r, -err); 211 "err = %d\n", aio_req_fd_r, -err);
212 } 212 }
213
214 return 0;
213} 215}
214 216
215static int aio_pid = -1; 217static int aio_pid = -1;
216 218
217static int init_aio_24(void) 219static int init_aio_24(void)
218{ 220{
219 unsigned long stack; 221 unsigned long stack;
220 int fds[2], err; 222 int fds[2], err;
221 223
222 err = os_pipe(fds, 1, 1); 224 err = os_pipe(fds, 1, 1);
223 if(err) 225 if(err)
224 goto out; 226 goto out;
225 227
226 aio_req_fd_w = fds[0]; 228 aio_req_fd_w = fds[0];
227 aio_req_fd_r = fds[1]; 229 aio_req_fd_r = fds[1];
228 err = run_helper_thread(not_aio_thread, NULL, 230 err = run_helper_thread(not_aio_thread, NULL,
229 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 231 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
230 if(err < 0) 232 if(err < 0)
231 goto out_close_pipe; 233 goto out_close_pipe;
232 234
233 aio_pid = err; 235 aio_pid = err;
234 goto out; 236 goto out;
235 237
236 out_close_pipe: 238out_close_pipe:
237 os_close_file(fds[0]); 239 os_close_file(fds[0]);
238 os_close_file(fds[1]); 240 os_close_file(fds[1]);
239 aio_req_fd_w = -1; 241 aio_req_fd_w = -1;
240 aio_req_fd_r = -1; 242 aio_req_fd_r = -1;
241 out: 243out:
242#ifndef HAVE_AIO_ABI 244#ifndef HAVE_AIO_ABI
243 printk("/usr/include/linux/aio_abi.h not present during build\n"); 245 printk("/usr/include/linux/aio_abi.h not present during build\n");
244#endif 246#endif
245 printk("2.6 host AIO support not used - falling back to I/O " 247 printk("2.6 host AIO support not used - falling back to I/O "
246 "thread\n"); 248 "thread\n");
247 return 0; 249 return 0;
248} 250}
249 251
250#ifdef HAVE_AIO_ABI 252#ifdef HAVE_AIO_ABI
251#define DEFAULT_24_AIO 0 253#define DEFAULT_24_AIO 0
252static int init_aio_26(void) 254static int init_aio_26(void)
253{ 255{
254 unsigned long stack; 256 unsigned long stack;
255 int err; 257 int err;
256 258
257 if(io_setup(256, &ctx)){ 259 if(io_setup(256, &ctx)){
258 err = -errno; 260 err = -errno;
259 printk("aio_thread failed to initialize context, err = %d\n", 261 printk("aio_thread failed to initialize context, err = %d\n",
260 errno); 262 errno);
261 return err; 263 return err;
262 } 264 }
263 265
264 err = run_helper_thread(aio_thread, NULL, 266 err = run_helper_thread(aio_thread, NULL,
265 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); 267 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
266 if(err < 0) 268 if(err < 0)
267 return err; 269 return err;
268 270
269 aio_pid = err; 271 aio_pid = err;
270 272
271 printk("Using 2.6 host AIO\n"); 273 printk("Using 2.6 host AIO\n");
272 return 0; 274 return 0;
273} 275}
274 276
275static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 277static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
276 unsigned long long offset, struct aio_context *aio) 278 unsigned long long offset, struct aio_context *aio)
277{ 279{
278 struct aio_thread_reply reply; 280 struct aio_thread_reply reply;
279 int err; 281 int err;
280 282
281 err = do_aio(ctx, type, io_fd, buf, len, offset, aio); 283 err = do_aio(ctx, type, io_fd, buf, len, offset, aio);
282 if(err){ 284 if(err){
283 reply = ((struct aio_thread_reply) { .data = aio, 285 reply = ((struct aio_thread_reply) { .data = aio,
284 .err = err }); 286 .err = err });
285 err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); 287 err = os_write_file(aio->reply_fd, &reply, sizeof(reply));
286 if(err != sizeof(reply)) 288 if(err != sizeof(reply))
287 printk("submit_aio_26 - write failed, " 289 printk("submit_aio_26 - write failed, "
288 "fd = %d, err = %d\n", aio->reply_fd, -err); 290 "fd = %d, err = %d\n", aio->reply_fd, -err);
289 else err = 0; 291 else err = 0;
290 } 292 }
291 293
292 return err; 294 return err;
293} 295}
294 296
295#else 297#else
296#define DEFAULT_24_AIO 1 298#define DEFAULT_24_AIO 1
297static int init_aio_26(void) 299static int init_aio_26(void)
298{ 300{
299 return -ENOSYS; 301 return -ENOSYS;
300} 302}
301 303
302static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, 304static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
303 unsigned long long offset, struct aio_context *aio) 305 unsigned long long offset, struct aio_context *aio)
304{ 306{
305 return -ENOSYS; 307 return -ENOSYS;
306} 308}
307#endif 309#endif
308 310
@@ -310,8 +312,8 @@ static int aio_24 = DEFAULT_24_AIO;
310 312
311static int __init set_aio_24(char *name, int *add) 313static int __init set_aio_24(char *name, int *add)
312{ 314{
313 aio_24 = 1; 315 aio_24 = 1;
314 return 0; 316 return 0;
315} 317}
316 318
317__uml_setup("aio=2.4", set_aio_24, 319__uml_setup("aio=2.4", set_aio_24,
@@ -328,28 +330,27 @@ __uml_setup("aio=2.4", set_aio_24,
328 330
329static int init_aio(void) 331static int init_aio(void)
330{ 332{
331 int err; 333 int err;
332 334
333 CHOOSE_MODE(({ 335 CHOOSE_MODE(({ if(!aio_24){
334 if(!aio_24){ 336 printk("Disabling 2.6 AIO in tt mode\n");
335 printk("Disabling 2.6 AIO in tt mode\n"); 337 aio_24 = 1;
336 aio_24 = 1; 338 } }), (void) 0);
337 } }), (void) 0); 339
338 340 if(!aio_24){
339 if(!aio_24){ 341 err = init_aio_26();
340 err = init_aio_26(); 342 if(err && (errno == ENOSYS)){
341 if(err && (errno == ENOSYS)){ 343 printk("2.6 AIO not supported on the host - "
342 printk("2.6 AIO not supported on the host - " 344 "reverting to 2.4 AIO\n");
343 "reverting to 2.4 AIO\n"); 345 aio_24 = 1;
344 aio_24 = 1; 346 }
345 } 347 else return err;
346 else return err; 348 }
347 } 349
348 350 if(aio_24)
349 if(aio_24) 351 return init_aio_24();
350 return init_aio_24(); 352
351 353 return 0;
352 return 0;
353} 354}
354 355
355/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio 356/* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio
@@ -362,8 +363,8 @@ __initcall(init_aio);
362 363
363static void exit_aio(void) 364static void exit_aio(void)
364{ 365{
365 if(aio_pid != -1) 366 if(aio_pid != -1)
366 os_kill_process(aio_pid, 1); 367 os_kill_process(aio_pid, 1);
367} 368}
368 369
369__uml_exitcall(exit_aio); 370__uml_exitcall(exit_aio);
@@ -371,30 +372,30 @@ __uml_exitcall(exit_aio);
371static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, 372static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
372 unsigned long long offset, struct aio_context *aio) 373 unsigned long long offset, struct aio_context *aio)
373{ 374{
374 struct aio_thread_req req = { .type = type, 375 struct aio_thread_req req = { .type = type,
375 .io_fd = io_fd, 376 .io_fd = io_fd,
376 .offset = offset, 377 .offset = offset,
377 .buf = buf, 378 .buf = buf,
378 .len = len, 379 .len = len,
379 .aio = aio, 380 .aio = aio,
380 }; 381 };
381 int err; 382 int err;
382 383
383 err = os_write_file(aio_req_fd_w, &req, sizeof(req)); 384 err = os_write_file(aio_req_fd_w, &req, sizeof(req));
384 if(err == sizeof(req)) 385 if(err == sizeof(req))
385 err = 0; 386 err = 0;
386 387
387 return err; 388 return err;
388} 389}
389 390
390int submit_aio(enum aio_type type, int io_fd, char *buf, int len, 391int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
391 unsigned long long offset, int reply_fd, 392 unsigned long long offset, int reply_fd,
392 struct aio_context *aio) 393 struct aio_context *aio)
393{ 394{
394 aio->reply_fd = reply_fd; 395 aio->reply_fd = reply_fd;
395 if(aio_24) 396 if(aio_24)
396 return submit_aio_24(type, io_fd, buf, len, offset, aio); 397 return submit_aio_24(type, io_fd, buf, len, offset, aio);
397 else { 398 else {
398 return submit_aio_26(type, io_fd, buf, len, offset, aio); 399 return submit_aio_26(type, io_fd, buf, len, offset, aio);
399 } 400 }
400} 401}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 23da27d225..172c847445 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -16,7 +16,6 @@
16#include "user_util.h" 16#include "user_util.h"
17#include "kern_util.h" 17#include "kern_util.h"
18#include "mem_user.h" 18#include "mem_user.h"
19#include "signal_user.h"
20#include "time_user.h" 19#include "time_user.h"
21#include "irq_user.h" 20#include "irq_user.h"
22#include "user.h" 21#include "user.h"
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index d9c52387c4..39815c6b5e 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -15,7 +15,6 @@
15#include "os.h" 15#include "os.h"
16#include "user.h" 16#include "user.h"
17#include "user_util.h" 17#include "user_util.h"
18#include "signal_user.h"
19#include "process.h" 18#include "process.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "kern_util.h" 20#include "kern_util.h"
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c7bfd5ee39..c1f46a0fef 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -4,9 +4,22 @@
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7#include <stdio.h>
8#include <unistd.h>
9#include <stdlib.h>
10#include <errno.h>
11#include <stdarg.h>
12#include <string.h>
13#include <sys/mman.h>
14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h"
17#include "signal_kern.h"
18#include "sysdep/sigcontext.h"
19#include "sysdep/signal.h"
20#include "sigcontext.h"
7#include "time_user.h" 21#include "time_user.h"
8#include "mode.h" 22#include "mode.h"
9#include "sysdep/signal.h"
10 23
11void sig_handler(ARCH_SIGHDLR_PARAM) 24void sig_handler(ARCH_SIGHDLR_PARAM)
12{ 25{
@@ -36,13 +49,138 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
36 switch_timers(1); 49 switch_timers(1);
37} 50}
38 51
39/* 52void set_sigstack(void *sig_stack, int size)
40 * Overrides for Emacs so that we follow Linus's tabbing style. 53{
41 * Emacs will notice this stuff at the end of the file and automatically 54 stack_t stack = ((stack_t) { .ss_flags = 0,
42 * adjust the settings for this buffer only. This must remain at the end 55 .ss_sp = (__ptr_t) sig_stack,
43 * of the file. 56 .ss_size = size - sizeof(void *) });
44 * --------------------------------------------------------------------------- 57
45 * Local variables: 58 if(sigaltstack(&stack, NULL) != 0)
46 * c-file-style: "linux" 59 panic("enabling signal stack failed, errno = %d\n", errno);
47 * End: 60}
61
62void remove_sigstack(void)
63{
64 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
65 .ss_sp = NULL,
66 .ss_size = 0 });
67
68 if(sigaltstack(&stack, NULL) != 0)
69 panic("disabling signal stack failed, errno = %d\n", errno);
70}
71
72void set_handler(int sig, void (*handler)(int), int flags, ...)
73{
74 struct sigaction action;
75 va_list ap;
76 int mask;
77
78 va_start(ap, flags);
79 action.sa_handler = handler;
80 sigemptyset(&action.sa_mask);
81 while((mask = va_arg(ap, int)) != -1){
82 sigaddset(&action.sa_mask, mask);
83 }
84 va_end(ap);
85 action.sa_flags = flags;
86 action.sa_restorer = NULL;
87 if(sigaction(sig, &action, NULL) < 0)
88 panic("sigaction failed");
89}
90
91int change_sig(int signal, int on)
92{
93 sigset_t sigset, old;
94
95 sigemptyset(&sigset);
96 sigaddset(&sigset, signal);
97 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
98 return(!sigismember(&old, signal));
99}
100
101/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
102 * disable profiling; it's safe because the profiling code does not interact
103 * with the kernel code at all.*/
104
105static void change_signals(int type)
106{
107 sigset_t mask;
108
109 sigemptyset(&mask);
110 sigaddset(&mask, SIGVTALRM);
111 sigaddset(&mask, SIGALRM);
112 sigaddset(&mask, SIGIO);
113 if(sigprocmask(type, &mask, NULL) < 0)
114 panic("Failed to change signal mask - errno = %d", errno);
115}
116
117void block_signals(void)
118{
119 change_signals(SIG_BLOCK);
120}
121
122void unblock_signals(void)
123{
124 change_signals(SIG_UNBLOCK);
125}
126
127/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
128 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
129 * be able to profile all of UML, not just the non-critical sections. If
130 * profiling is not thread-safe, then that is not my problem. We can disable
131 * profiling when SMP is enabled in that case.
48 */ 132 */
133#define SIGIO_BIT 0
134#define SIGVTALRM_BIT 1
135
136static int enable_mask(sigset_t *mask)
137{
138 int sigs;
139
140 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
141 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
142 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
143 return(sigs);
144}
145
146int get_signals(void)
147{
148 sigset_t mask;
149
150 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
151 panic("Failed to get signal mask");
152 return(enable_mask(&mask));
153}
154
155int set_signals(int enable)
156{
157 sigset_t mask;
158 int ret;
159
160 sigemptyset(&mask);
161 if(enable & (1 << SIGIO_BIT))
162 sigaddset(&mask, SIGIO);
163 if(enable & (1 << SIGVTALRM_BIT)){
164 sigaddset(&mask, SIGVTALRM);
165 sigaddset(&mask, SIGALRM);
166 }
167
168 /* This is safe - sigprocmask is guaranteed to copy locally the
169 * value of new_set, do his work and then, at the end, write to
170 * old_set.
171 */
172 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
173 panic("Failed to enable signals");
174 ret = enable_mask(&mask);
175 sigemptyset(&mask);
176 if((enable & (1 << SIGIO_BIT)) == 0)
177 sigaddset(&mask, SIGIO);
178 if((enable & (1 << SIGVTALRM_BIT)) == 0){
179 sigaddset(&mask, SIGVTALRM);
180 sigaddset(&mask, SIGALRM);
181 }
182 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
183 panic("Failed to block signals");
184
185 return(ret);
186}
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
new file mode 100644
index 0000000000..eab5386d60
--- /dev/null
+++ b/arch/um/os-Linux/skas/Makefile
@@ -0,0 +1,10 @@
1#
2# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
3# Licensed under the GPL
4#
5
6obj-y := trap.o
7
8USER_OBJS := trap.o
9
10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/os-Linux/skas/trap.c
index 9950a6716f..9ad5fbec45 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -1,11 +1,10 @@
1/* 1/*
2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7#include <errno.h> 7#include <errno.h>
8#include "signal_user.h"
9#include "user_util.h" 8#include "user_util.h"
10#include "kern_util.h" 9#include "kern_util.h"
11#include "task.h" 10#include "task.h"
@@ -14,12 +13,13 @@
14#include "ptrace_user.h" 13#include "ptrace_user.h"
15#include "sysdep/ptrace.h" 14#include "sysdep/ptrace.h"
16#include "sysdep/ptrace_user.h" 15#include "sysdep/ptrace_user.h"
16#include "os.h"
17 17
18void sig_handler_common_skas(int sig, void *sc_ptr) 18void sig_handler_common_skas(int sig, void *sc_ptr)
19{ 19{
20 struct sigcontext *sc = sc_ptr; 20 struct sigcontext *sc = sc_ptr;
21 struct skas_regs *r; 21 struct skas_regs *r;
22 struct signal_info *info; 22 void (*handler)(int, union uml_pt_regs *);
23 int save_errno = errno; 23 int save_errno = errno;
24 int save_user; 24 int save_user;
25 25
@@ -34,17 +34,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
34 r = &TASK_REGS(get_current())->skas; 34 r = &TASK_REGS(get_current())->skas;
35 save_user = r->is_user; 35 save_user = r->is_user;
36 r->is_user = 0; 36 r->is_user = 0;
37 if ( sig == SIGFPE || sig == SIGSEGV || 37 if ( sig == SIGFPE || sig == SIGSEGV ||
38 sig == SIGBUS || sig == SIGILL || 38 sig == SIGBUS || sig == SIGILL ||
39 sig == SIGTRAP ) { 39 sig == SIGTRAP ) {
40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc); 40 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
41 } 41 }
42 42
43 change_sig(SIGUSR1, 1); 43 change_sig(SIGUSR1, 1);
44 info = &sig_info[sig];
45 if(!info->is_irq) unblock_signals();
46 44
47 (*info->handler)(sig, (union uml_pt_regs *) r); 45 handler = sig_info[sig];
46
47 /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
48 if (sig != SIGIO && sig != SIGWINCH &&
49 sig != SIGVTALRM && sig != SIGALRM)
50 unblock_signals();
51
52 handler(sig, (union uml_pt_regs *) r);
48 53
49 errno = save_errno; 54 errno = save_errno;
50 r->is_user = save_user; 55 r->is_user = save_user;
@@ -54,25 +59,15 @@ extern int ptrace_faultinfo;
54 59
55void user_signal(int sig, union uml_pt_regs *regs, int pid) 60void user_signal(int sig, union uml_pt_regs *regs, int pid)
56{ 61{
57 struct signal_info *info; 62 void (*handler)(int, union uml_pt_regs *);
58 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || 63 int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
59 (sig == SIGILL) || (sig == SIGTRAP)); 64 (sig == SIGILL) || (sig == SIGTRAP));
60 65
61 if (segv) 66 if (segv)
62 get_skas_faultinfo(pid, &regs->skas.faultinfo); 67 get_skas_faultinfo(pid, &regs->skas.faultinfo);
63 info = &sig_info[sig]; 68
64 (*info->handler)(sig, regs); 69 handler = sig_info[sig];
70 handler(sig, (union uml_pt_regs *) regs);
65 71
66 unblock_signals(); 72 unblock_signals();
67} 73}
68
69/*
70 * Overrides for Emacs so that we follow Linus's tabbing style.
71 * Emacs will notice this stuff at the end of the file and automatically
72 * adjust the settings for this buffer only. This must remain at the end
73 * of the file.
74 * ---------------------------------------------------------------------------
75 * Local variables:
76 * c-file-style: "linux"
77 * End:
78 */
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 29a9e3f437..b47e5e71d1 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -24,7 +24,6 @@
24#include "kern_util.h" 24#include "kern_util.h"
25#include "user.h" 25#include "user.h"
26#include "signal_kern.h" 26#include "signal_kern.h"
27#include "signal_user.h"
28#include "sysdep/ptrace.h" 27#include "sysdep/ptrace.h"
29#include "sysdep/sigcontext.h" 28#include "sysdep/sigcontext.h"
30#include "irq_user.h" 29#include "irq_user.h"
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
new file mode 100644
index 0000000000..321e1c8e22
--- /dev/null
+++ b/arch/um/os-Linux/trap.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <signal.h>
8#include <setjmp.h>
9#include "kern_util.h"
10#include "user_util.h"
11#include "os.h"
12#include "mode.h"
13
14void usr2_handler(int sig, union uml_pt_regs *regs)
15{
16 CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
17}
18
19void (*sig_info[NSIG])(int, union uml_pt_regs *);
20
21void os_fill_handlinfo(struct kern_handlers h)
22{
23 sig_info[SIGTRAP] = h.relay_signal;
24 sig_info[SIGFPE] = h.relay_signal;
25 sig_info[SIGILL] = h.relay_signal;
26 sig_info[SIGWINCH] = h.winch;
27 sig_info[SIGBUS] = h.bus_handler;
28 sig_info[SIGSEGV] = h.page_fault;
29 sig_info[SIGIO] = h.sigio_handler;
30 sig_info[SIGVTALRM] = h.timer_handler;
31 sig_info[SIGALRM] = h.timer_handler;
32 sig_info[SIGUSR2] = usr2_handler;
33}
34
35void do_longjmp(void *b, int val)
36{
37 sigjmp_buf *buf = b;
38
39 siglongjmp(*buf, val);
40}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index a6db887793..cb2648b79d 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -23,7 +23,6 @@
23#include "kern_util.h" 23#include "kern_util.h"
24#include "user.h" 24#include "user.h"
25#include "signal_kern.h" 25#include "signal_kern.h"
26#include "signal_user.h"
27#include "sysdep/ptrace.h" 26#include "sysdep/ptrace.h"
28#include "sysdep/sigcontext.h" 27#include "sysdep/sigcontext.h"
29#include "irq_user.h" 28#include "irq_user.h"
@@ -50,6 +49,20 @@ int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
50 return(0); 49 return(0);
51} 50}
52 51
52void kill_child_dead(int pid)
53{
54 kill(pid, SIGKILL);
55 kill(pid, SIGCONT);
56 do {
57 int n;
58 CATCH_EINTR(n = waitpid(pid, NULL, 0));
59 if (n > 0)
60 kill(pid, SIGCONT);
61 else
62 break;
63 } while(1);
64}
65
53/* 66/*
54 *------------------------- 67 *-------------------------
55 * only for tt mode (will be deleted in future...) 68 * only for tt mode (will be deleted in future...)
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
new file mode 100644
index 0000000000..ecf107ae5a
--- /dev/null
+++ b/arch/um/os-Linux/umid.c
@@ -0,0 +1,335 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <errno.h>
6#include <signal.h>
7#include <dirent.h>
8#include <sys/fcntl.h>
9#include <sys/stat.h>
10#include <sys/param.h>
11#include "init.h"
12#include "os.h"
13#include "user.h"
14#include "mode.h"
15
16#define UML_DIR "~/.uml/"
17
18#define UMID_LEN 64
19
20/* Changed by set_umid, which is run early in boot */
21char umid[UMID_LEN] = { 0 };
22
23/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
24static char *uml_dir = UML_DIR;
25
26static int __init make_uml_dir(void)
27{
28 char dir[512] = { '\0' };
29 int len, err;
30
31 if(*uml_dir == '~'){
32 char *home = getenv("HOME");
33
34 err = -ENOENT;
35 if(home == NULL){
36 printk("make_uml_dir : no value in environment for "
37 "$HOME\n");
38 goto err;
39 }
40 strlcpy(dir, home, sizeof(dir));
41 uml_dir++;
42 }
43 strlcat(dir, uml_dir, sizeof(dir));
44 len = strlen(dir);
45 if (len > 0 && dir[len - 1] != '/')
46 strlcat(dir, "/", sizeof(dir));
47
48 err = -ENOMEM;
49 uml_dir = malloc(strlen(dir) + 1);
50 if (uml_dir == NULL) {
51 printf("make_uml_dir : malloc failed, errno = %d\n", errno);
52 goto err;
53 }
54 strcpy(uml_dir, dir);
55
56 if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
57 printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno));
58 err = -errno;
59 goto err_free;
60 }
61 return 0;
62
63err_free:
64 free(uml_dir);
65err:
66 uml_dir = NULL;
67 return err;
68}
69
70static int actually_do_remove(char *dir)
71{
72 DIR *directory;
73 struct dirent *ent;
74 int len;
75 char file[256];
76
77 directory = opendir(dir);
78 if(directory == NULL)
79 return -errno;
80
81 while((ent = readdir(directory)) != NULL){
82 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
83 continue;
84 len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
85 if(len > sizeof(file))
86 return -E2BIG;
87
88 sprintf(file, "%s/%s", dir, ent->d_name);
89 if(unlink(file) < 0)
90 return -errno;
91 }
92 if(rmdir(dir) < 0)
93 return -errno;
94
95 return 0;
96}
97
98/* This says that there isn't already a user of the specified directory even if
99 * there are errors during the checking. This is because if these errors
100 * happen, the directory is unusable by the pre-existing UML, so we might as
101 * well take it over. This could happen either by
102 * the existing UML somehow corrupting its umid directory
103 * something other than UML sticking stuff in the directory
104 * this boot racing with a shutdown of the other UML
105 * In any of these cases, the directory isn't useful for anything else.
106 */
107
108static int not_dead_yet(char *dir)
109{
110 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
111 char pid[sizeof("nnnnn\0")], *end;
112 int dead, fd, p, n, err;
113
114 n = snprintf(file, sizeof(file), "%s/pid", dir);
115 if(n >= sizeof(file)){
116 printk("not_dead_yet - pid filename too long\n");
117 err = -E2BIG;
118 goto out;
119 }
120
121 dead = 0;
122 fd = open(file, O_RDONLY);
123 if(fd < 0){
124 if(fd != -ENOENT){
125 printk("not_dead_yet : couldn't open pid file '%s', "
126 "err = %d\n", file, -fd);
127 }
128 goto out;
129 }
130
131 err = 0;
132 n = read(fd, pid, sizeof(pid));
133 if(n <= 0){
134 printk("not_dead_yet : couldn't read pid file '%s', "
135 "err = %d\n", file, -n);
136 goto out_close;
137 }
138
139 p = strtoul(pid, &end, 0);
140 if(end == pid){
141 printk("not_dead_yet : couldn't parse pid file '%s', "
142 "errno = %d\n", file, errno);
143 goto out_close;
144 }
145
146 if((kill(p, 0) == 0) || (errno != ESRCH))
147 return 1;
148
149 err = actually_do_remove(dir);
150 if(err)
151 printk("not_dead_yet - actually_do_remove failed with "
152 "err = %d\n", err);
153
154 return err;
155
156 out_close:
157 close(fd);
158 out:
159 return 0;
160}
161
162static void __init create_pid_file(void)
163{
164 char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
165 char pid[sizeof("nnnnn\0")];
166 int fd, n;
167
168 if(umid_file_name("pid", file, sizeof(file)))
169 return;
170
171 fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
172 if(fd < 0){
173 printk("Open of machine pid file \"%s\" failed: %s\n",
174 file, strerror(-fd));
175 return;
176 }
177
178 snprintf(pid, sizeof(pid), "%d\n", getpid());
179 n = write(fd, pid, strlen(pid));
180 if(n != strlen(pid))
181 printk("Write of pid file failed - err = %d\n", -n);
182
183 close(fd);
184}
185
186int __init set_umid(char *name)
187{
188 if(strlen(name) > UMID_LEN - 1)
189 return -E2BIG;
190
191 strlcpy(umid, name, sizeof(umid));
192
193 return 0;
194}
195
196static int umid_setup = 0;
197
198int __init make_umid(void)
199{
200 int fd, err;
201 char tmp[256];
202
203 if(umid_setup)
204 return 0;
205
206 make_uml_dir();
207
208 if(*umid == '\0'){
209 strlcpy(tmp, uml_dir, sizeof(tmp));
210 strlcat(tmp, "XXXXXX", sizeof(tmp));
211 fd = mkstemp(tmp);
212 if(fd < 0){
213 printk("make_umid - mkstemp(%s) failed: %s\n",
214 tmp, strerror(errno));
215 err = -errno;
216 goto err;
217 }
218
219 close(fd);
220
221 set_umid(&tmp[strlen(uml_dir)]);
222
223 /* There's a nice tiny little race between this unlink and
224 * the mkdir below. It'd be nice if there were a mkstemp
225 * for directories.
226 */
227 if(unlink(tmp)){
228 err = -errno;
229 goto err;
230 }
231 }
232
233 snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
234 err = mkdir(tmp, 0777);
235 if(err < 0){
236 err = -errno;
237 if(errno != EEXIST)
238 goto err;
239
240 if(not_dead_yet(tmp) < 0)
241 goto err;
242
243 err = mkdir(tmp, 0777);
244 }
245 if(err < 0){
246 printk("Failed to create '%s' - err = %d\n", umid, err);
247 goto err_rmdir;
248 }
249
250 umid_setup = 1;
251
252 create_pid_file();
253
254 return 0;
255
256 err_rmdir:
257 rmdir(tmp);
258 err:
259 return err;
260}
261
262static int __init make_umid_init(void)
263{
264 make_umid();
265
266 return 0;
267}
268
269__initcall(make_umid_init);
270
271int __init umid_file_name(char *name, char *buf, int len)
272{
273 int n, err;
274
275 err = make_umid();
276 if(err)
277 return err;
278
279 n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
280 if(n >= len){
281 printk("umid_file_name : buffer too short\n");
282 return -E2BIG;
283 }
284
285 return 0;
286}
287
288char *get_umid(void)
289{
290 return umid;
291}
292
293static int __init set_uml_dir(char *name, int *add)
294{
295 if(*name == '\0'){
296 printf("uml_dir can't be an empty string\n");
297 return 0;
298 }
299
300 if(name[strlen(name) - 1] == '/'){
301 uml_dir = name;
302 return 0;
303 }
304
305 uml_dir = malloc(strlen(name) + 2);
306 if(uml_dir == NULL){
307 printf("Failed to malloc uml_dir - error = %d\n", errno);
308
309 /* Return 0 here because do_initcalls doesn't look at
310 * the return value.
311 */
312 return 0;
313 }
314 sprintf(uml_dir, "%s/", name);
315
316 return 0;
317}
318
319__uml_setup("uml_dir=", set_uml_dir,
320"uml_dir=<directory>\n"
321" The location to place the pid and umid files.\n\n"
322);
323
324static void remove_umid_dir(void)
325{
326 char dir[strlen(uml_dir) + UMID_LEN + 1], err;
327
328 sprintf(dir, "%s%s", uml_dir, umid);
329 err = actually_do_remove(dir);
330 if(err)
331 printf("remove_umid_dir - actually_do_remove failed with "
332 "err = %d\n", err);
333}
334
335__uml_exitcall(remove_umid_dir);
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 16bc19928b..7cd1a82dc8 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -10,7 +10,6 @@
10#include "asm/uaccess.h" 10#include "asm/uaccess.h"
11#include "asm/unistd.h" 11#include "asm/unistd.h"
12#include "frame_kern.h" 12#include "frame_kern.h"
13#include "signal_user.h"
14#include "sigcontext.h" 13#include "sigcontext.h"
15#include "registers.h" 14#include "registers.h"
16#include "mode.h" 15#include "mode.h"