aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/mconsole_kern.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index b5217bd7bc41..e9bbc14f3655 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"
@@ -480,6 +481,82 @@ void mconsole_sysrq(struct mc_request *req)
480} 481}
481#endif 482#endif
482 483
484static DEFINE_SPINLOCK(console_lock);
485static LIST_HEAD(clients);
486static char console_buf[MCONSOLE_MAX_DATA];
487static int console_index = 0;
488
489static void console_write(struct console *console, const char *string,
490 unsigned len)
491{
492 struct list_head *ele;
493 int n;
494
495 if(list_empty(&clients))
496 return;
497
498 while(1){
499 n = min(len, ARRAY_SIZE(console_buf) - console_index);
500 strncpy(&console_buf[console_index], string, n);
501 console_index += n;
502 string += n;
503 len -= n;
504 if(len == 0)
505 return;
506
507 list_for_each(ele, &clients){
508 struct mconsole_entry *entry;
509
510 entry = list_entry(ele, struct mconsole_entry, list);
511 mconsole_reply_len(&entry->request, console_buf,
512 console_index, 0, 1);
513 }
514
515 console_index = 0;
516 }
517}
518
519static struct console mc_console = { .name = "mc",
520 .write = console_write,
521 .flags = CON_PRINTBUFFER | CON_ENABLED,
522 .index = -1 };
523
524static int mc_add_console(void)
525{
526 register_console(&mc_console);
527 return 0;
528}
529
530late_initcall(mc_add_console);
531
532static void with_console(struct mc_request *req, void (*proc)(void *),
533 void *arg)
534{
535 struct mconsole_entry entry;
536 unsigned long flags;
537
538 INIT_LIST_HEAD(&entry.list);
539 entry.request = *req;
540 list_add(&entry.list, &clients);
541 spin_lock_irqsave(&console_lock, flags);
542
543 (*proc)(arg);
544
545 mconsole_reply_len(req, console_buf, console_index, 0, 0);
546 console_index = 0;
547
548 spin_unlock_irqrestore(&console_lock, flags);
549 list_del(&entry.list);
550}
551
552static void stack_proc(void *arg)
553{
554 struct task_struct *from = current, *to = arg;
555
556 to->thread.saved_task = from;
557 switch_to(from, to, from);
558}
559
483/* Mconsole stack trace 560/* Mconsole stack trace
484 * Added by Allan Graves, Jeff Dike 561 * Added by Allan Graves, Jeff Dike
485 * Dumps a stacks registers to the linux console. 562 * Dumps a stacks registers to the linux console.
@@ -489,7 +566,7 @@ void do_stack(struct mc_request *req)
489{ 566{
490 char *ptr = req->request.data; 567 char *ptr = req->request.data;
491 int pid_requested= -1; 568 int pid_requested= -1;
492 struct task_struct *from = NULL; 569 struct task_struct *from = NULL;
493 struct task_struct *to = NULL; 570 struct task_struct *to = NULL;
494 571
495 /* Would be nice: 572 /* Would be nice:
@@ -507,17 +584,15 @@ void do_stack(struct mc_request *req)
507 return; 584 return;
508 } 585 }
509 586
510 from = current; 587 from = current;
511 to = find_task_by_pid(pid_requested);
512 588
589 to = find_task_by_pid(pid_requested);
513 if((to == NULL) || (pid_requested == 0)) { 590 if((to == NULL) || (pid_requested == 0)) {
514 mconsole_reply(req, "Couldn't find that pid", 1, 0); 591 mconsole_reply(req, "Couldn't find that pid", 1, 0);
515 return; 592 return;
516 } 593 }
517 to->thread.saved_task = current;
518 594
519 switch_to(from, to, from); 595 with_console(req, stack_proc, to);
520 mconsole_reply(req, "Stack Dumped to console and message log", 0, 0);
521} 596}
522 597
523void mconsole_stack(struct mc_request *req) 598void mconsole_stack(struct mc_request *req)