8 #include <linux/ctype.h>
9 #include <linux/string.h>
11 #include <linux/list.h>
13 #include <linux/module.h>
15 #include <linux/reboot.h>
17 #include <linux/slab.h>
19 #include <linux/utsname.h>
20 #include <linux/socket.h>
27 #include <asm/uaccess.h>
28 #include <asm/switch_to.h>
46 .notifier_call = do_unlink_socket,
62 while (!list_empty(&mc_requests)) {
84 (*req.cmd->handler)(&req);
92 list_add(&new->list, &mc_requests);
96 if (!list_empty(&mc_requests))
106 sprintf(version,
"%s %s %s %s %s", utsname()->sysname,
107 utsname()->nodename, utsname()->
release, utsname()->version,
175 #define UML_MCONSOLE_HELPTEXT \
177 version - Get kernel version \n\
178 help - Print this message \n\
180 reboot - Reboot UML \n\
181 config <dev>=<config> - Add a new device to UML; \n\
182 same syntax as command line \n\
183 config <dev> - Query the configuration of a device \n\
184 remove <dev> - Remove a device from UML \n\
185 sysrq <letter> - Performs the SysRq action controlled by the letter \n\
186 cad - invoke the Ctrl-Alt-Del handler \n\
187 stop - pause the UML; it will do nothing until it receives a 'go' \n\
188 go - continue the UML after a 'stop' \n\
189 log <string> - make UML enter <string> into the kernel log\n\
190 proc <file> - returns the contents of the UML's /proc/<file>\n\
191 stack <pid> - returns the stack of the specified pid\n\
238 old_regs = set_irq_regs((
struct pt_regs *)&req->
regs);
240 set_irq_regs(old_regs);
243 (*req->
cmd->handler)(req);
255 spin_lock(&mc_devices_lock);
256 BUG_ON(!list_empty(&new->list));
257 list_add(&new->list, &mconsole_devices);
258 spin_unlock(&mc_devices_lock);
274 #define UNPLUGGED_PER_PAGE \
275 ((PAGE_SIZE - sizeof(struct list_head)) / sizeof(unsigned long))
283 static unsigned long long unplugged_pages_count = 0;
287 static int mem_config(
char *
str,
char **error_out)
289 unsigned long long diff;
294 *error_out =
"Expected '=' after 'mem'";
301 else if (str[0] ==
'+') {
305 *error_out =
"Expected increment to start with '-' or '+'";
312 *error_out =
"Failed to parse memory increment";
319 for (i = 0; i < diff; i++) {
329 if (unplug_index > 0)
330 addr = unplugged->
pages[--unplug_index];
338 unplugged_pages_count--;
362 "memory - errno = %d\n", err);
363 *error_out =
"Failed to release memory";
369 unplugged_pages_count++;
380 static int mem_get_config(
char *name,
char *str,
int size,
char **error_out)
382 char buf[
sizeof(
"18446744073709551615")];
391 static int mem_id(
char **str,
int *start_out,
int *end_out)
399 static int mem_remove(
int n,
char **error_out)
401 *error_out =
"Memory doesn't support the remove operation";
408 .config = mem_config,
409 .get_config = mem_get_config,
411 .remove = mem_remove,
414 static int __init mem_mc_init(
void)
419 "hotplug won't be supported\n");
425 #define CONFIG_BUF_SIZE 64
427 static void mconsole_get_config(
int (*
get_config)(
char *,
char *,
int,
455 if (buf != default_buf)
466 if (buf != default_buf)
478 dev = mconsole_find_dev(ptr);
486 while ((*ptr !=
'=') && (*ptr !=
'\0'))
490 err = (*dev->
config)(name, &error_string);
493 else mconsole_get_config(dev->
get_config, req, name);
505 dev = mconsole_find_dev(ptr);
514 n = (*dev->
id)(&ptr, &start, &end);
516 err_msg =
"Couldn't parse device number";
519 else if ((n < start) || (n >
end)) {
520 sprintf(error,
"Invalid device number - must be between "
521 "%d and %d", start, end);
534 err_msg =
"Device doesn't exist";
538 err_msg =
"Device is currently open";
556 static void console_write(
struct console *
console,
const char *
string,
562 if (list_empty(&clients))
567 strncpy(console_buf,
string, n);
580 static struct console mc_console = { .name =
"mc",
581 .write = console_write,
585 static int mc_add_console(
void)
593 static void with_console(
struct mc_request *req,
void (*proc)(
void *),
601 list_add(&
entry.list, &clients);
602 spin_unlock_irqrestore(&client_lock, flags);
610 spin_unlock_irqrestore(&client_lock, flags);
613 #ifdef CONFIG_MAGIC_SYSRQ
617 static void sysrq_proc(
void *
arg)
637 with_console(req, sysrq_proc, ptr);
646 static void stack_proc(
void *
arg)
650 to->thread.saved_task =
from;
651 rcu_switch(from, to);
664 int pid_requested= -1;
680 if (
sscanf(ptr,
"%d", &pid_requested) == 0) {
686 if ((to ==
NULL) || (pid_requested == 0)) {
690 with_console(req, stack_proc, to);
697 static char *notify_socket =
NULL;
699 static int __init mconsole_init(
void)
727 if (notify_socket !=
NULL) {
729 if (notify_socket !=
NULL)
748 static ssize_t mconsole_proc_write(
struct file *file,
772 .write = mconsole_proc_write,
776 static int create_proc_mconsole(
void)
780 if (notify_socket ==
NULL)
783 ent = proc_create(
"mconsole", 0200,
NULL, &mconsole_proc_fops);
796 spin_lock(¬ify_spinlock);
801 spin_unlock(¬ify_spinlock);
806 #define NOTIFY "notify:"
808 static int mconsole_setup(
char *str)
814 else printk(
KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str);
818 __setup(
"mconsole=", mconsole_setup);
821 "mconsole=notify:<socket>\n"
822 " Requests that the mconsole driver send a message to the named Unix\n"
823 " socket containing the name of the mconsole socket. This also serves\n"
824 " to notify outside processes when UML has booted far enough to respond\n"
825 " to mconsole requests.\n\n"
833 if (notify_socket ==
NULL)
842 .notifier_call = notify_panic,
847 static int add_notifier(
void)
850 &panic_exit_notifier);
858 return notify_socket;