direct-io.hg

view xen/drivers/char/console.c @ 15399:45a44a9cbe8d

Enhance guest memory accessor macros so that source operands can be
pointers to const or arrays.

Only build-tested on ia64, and untested for powerpc (which, however,
is almost identical to ia64, except for an apparent bug in the original
version of __copy_field_{from,to}_guest in that the field offset was
multiplied by the field size).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kfraser@localhost.localdomain
date Wed Jun 20 15:29:53 2007 +0100 (2007-06-20)
parents 35e38c9048c8
children
line source
1 /******************************************************************************
2 * console.c
3 *
4 * Emergency console I/O for Xen and the domain-0 guest OS.
5 *
6 * Copyright (c) 2002-2004, K A Fraser.
7 *
8 * Added printf_ratelimit
9 * Taken from Linux - Author: Andi Kleen (net_ratelimit)
10 * Ported to Xen - Steven Rostedt - Red Hat
11 */
13 #include <xen/stdarg.h>
14 #include <xen/config.h>
15 #include <xen/version.h>
16 #include <xen/init.h>
17 #include <xen/lib.h>
18 #include <xen/errno.h>
19 #include <xen/event.h>
20 #include <xen/spinlock.h>
21 #include <xen/console.h>
22 #include <xen/serial.h>
23 #include <xen/softirq.h>
24 #include <xen/keyhandler.h>
25 #include <xen/mm.h>
26 #include <xen/delay.h>
27 #include <xen/guest_access.h>
28 #include <xen/shutdown.h>
29 #include <xen/vga.h>
30 #include <xen/kexec.h>
31 #include <asm/current.h>
32 #include <asm/debugger.h>
33 #include <asm/io.h>
34 #include <asm/div64.h>
36 /* console: comma-separated list of console outputs. */
37 static char opt_console[30] = OPT_CONSOLE_STR;
38 string_param("console", opt_console);
40 /* conswitch: a character pair controlling console switching. */
41 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
42 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
43 /* boots. Any other value, or omitting the char, enables auto-switch */
44 static unsigned char opt_conswitch[5] = "a";
45 string_param("conswitch", opt_conswitch);
47 /* sync_console: force synchronous console output (useful for debugging). */
48 static int opt_sync_console;
49 boolean_param("sync_console", opt_sync_console);
51 /* console_to_ring: send guest (incl. dom 0) console data to console ring. */
52 static int opt_console_to_ring;
53 boolean_param("console_to_ring", opt_console_to_ring);
55 #define CONRING_SIZE 16384
56 #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
57 static char conring[CONRING_SIZE];
58 static unsigned int conringc, conringp;
60 static char printk_prefix[16] = "";
62 static int sercon_handle = -1;
64 static DEFINE_SPINLOCK(console_lock);
66 /*
67 * To control the amount of printing, thresholds are added.
68 * These thresholds correspond to the XENLOG logging levels.
69 * There's an upper and lower threshold for non-guest messages and for
70 * guest-provoked messages. This works as follows, for a given log level L:
71 *
72 * L < lower_threshold : always logged
73 * lower_threshold <= L < upper_threshold : rate-limited logging
74 * upper_threshold <= L : never logged
75 *
76 * Note, in the above algorithm, to disable rate limiting simply make
77 * the lower threshold equal to the upper.
78 */
79 #ifdef NDEBUG
80 #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
81 #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */
82 #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
83 #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */
84 #else
85 #define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */
86 #define XENLOG_LOWER_THRESHOLD 4 /* Print everything */
87 #define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */
88 #define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */
89 #endif
90 /*
91 * The XENLOG_DEFAULT is the default given to printks that
92 * do not have any print level associated with them.
93 */
94 #define XENLOG_DEFAULT 1 /* XENLOG_WARNING */
95 #define XENLOG_GUEST_DEFAULT 1 /* XENLOG_WARNING */
97 static int xenlog_upper_thresh = XENLOG_UPPER_THRESHOLD;
98 static int xenlog_lower_thresh = XENLOG_LOWER_THRESHOLD;
99 static int xenlog_guest_upper_thresh = XENLOG_GUEST_UPPER_THRESHOLD;
100 static int xenlog_guest_lower_thresh = XENLOG_GUEST_LOWER_THRESHOLD;
102 static void parse_loglvl(char *s);
103 static void parse_guest_loglvl(char *s);
105 /*
106 * <lvl> := none|error|warning|info|debug|all
107 * loglvl=<lvl_print_always>[/<lvl_print_ratelimit>]
108 * <lvl_print_always>: log level which is always printed
109 * <lvl_print_rlimit>: log level which is rate-limit printed
110 * Similar definitions for guest_loglvl, but applies to guest tracing.
111 * Defaults: loglvl=warning ; guest_loglvl=none/warning
112 */
113 custom_param("loglvl", parse_loglvl);
114 custom_param("guest_loglvl", parse_guest_loglvl);
116 static atomic_t print_everything = ATOMIC_INIT(0);
118 #define ___parse_loglvl(s, ps, lvlstr, lvlnum) \
119 if ( !strncmp((s), (lvlstr), strlen(lvlstr)) ) { \
120 *(ps) = (s) + strlen(lvlstr); \
121 return (lvlnum); \
122 }
124 static int __init __parse_loglvl(char *s, char **ps)
125 {
126 ___parse_loglvl(s, ps, "none", 0);
127 ___parse_loglvl(s, ps, "error", 1);
128 ___parse_loglvl(s, ps, "warning", 2);
129 ___parse_loglvl(s, ps, "info", 3);
130 ___parse_loglvl(s, ps, "debug", 4);
131 ___parse_loglvl(s, ps, "all", 4);
132 return 2; /* sane fallback */
133 }
135 static void __init _parse_loglvl(char *s, int *lower, int *upper)
136 {
137 *lower = *upper = __parse_loglvl(s, &s);
138 if ( *s == '/' )
139 *upper = __parse_loglvl(s+1, &s);
140 if ( *upper < *lower )
141 *upper = *lower;
142 }
144 static void __init parse_loglvl(char *s)
145 {
146 _parse_loglvl(s, &xenlog_lower_thresh, &xenlog_upper_thresh);
147 }
149 static void __init parse_guest_loglvl(char *s)
150 {
151 _parse_loglvl(s, &xenlog_guest_lower_thresh, &xenlog_guest_upper_thresh);
152 }
154 static char * __init loglvl_str(int lvl)
155 {
156 switch ( lvl )
157 {
158 case 0: return "Nothing";
159 case 1: return "Errors";
160 case 2: return "Errors and warnings";
161 case 3: return "Errors, warnings and info";
162 case 4: return "All";
163 }
164 return "???";
165 }
167 /*
168 * ********************************************************
169 * *************** ACCESS TO CONSOLE RING *****************
170 * ********************************************************
171 */
173 static void putchar_console_ring(int c)
174 {
175 conring[CONRING_IDX_MASK(conringp++)] = c;
176 if ( (conringp - conringc) > CONRING_SIZE )
177 conringc = conringp - CONRING_SIZE;
178 }
180 long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear)
181 {
182 unsigned int idx, len, max, sofar, c;
183 unsigned long flags;
185 max = *pcount;
186 sofar = 0;
188 c = conringc;
189 while ( (c != conringp) && (sofar < max) )
190 {
191 idx = CONRING_IDX_MASK(c);
192 len = conringp - c;
193 if ( (idx + len) > CONRING_SIZE )
194 len = CONRING_SIZE - idx;
195 if ( (sofar + len) > max )
196 len = max - sofar;
197 if ( copy_to_guest_offset(str, sofar, &conring[idx], len) )
198 return -EFAULT;
199 sofar += len;
200 c += len;
201 }
203 if ( clear )
204 {
205 spin_lock_irqsave(&console_lock, flags);
206 if ( (conringp - c) > CONRING_SIZE )
207 conringc = conringp - CONRING_SIZE;
208 else
209 conringc = c;
210 spin_unlock_irqrestore(&console_lock, flags);
211 }
213 *pcount = sofar;
214 return 0;
215 }
218 /*
219 * *******************************************************
220 * *************** ACCESS TO SERIAL LINE *****************
221 * *******************************************************
222 */
224 /* Characters received over the serial line are buffered for domain 0. */
225 #define SERIAL_RX_SIZE 128
226 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
227 static char serial_rx_ring[SERIAL_RX_SIZE];
228 static unsigned int serial_rx_cons, serial_rx_prod;
230 static void (*serial_steal_fn)(const char *);
232 int console_steal(int handle, void (*fn)(const char *))
233 {
234 if ( (handle == -1) || (handle != sercon_handle) )
235 return 0;
237 if ( serial_steal_fn != NULL )
238 return -EBUSY;
240 serial_steal_fn = fn;
241 return 1;
242 }
244 void console_giveback(int id)
245 {
246 if ( id == 1 )
247 serial_steal_fn = NULL;
248 }
250 static void sercon_puts(const char *s)
251 {
252 if ( serial_steal_fn != NULL )
253 (*serial_steal_fn)(s);
254 else
255 serial_puts(sercon_handle, s);
256 }
258 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
259 #define SWITCH_CODE (opt_conswitch[0]-'a'+1)
260 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
262 static void switch_serial_input(void)
263 {
264 static char *input_str[2] = { "DOM0", "Xen" };
265 xen_rx = !xen_rx;
266 if ( (SWITCH_CODE != 0) && (dom0 != NULL) )
267 {
268 printk("*** Serial input -> %s "
269 "(type 'CTRL-%c' three times to switch input to %s).\n",
270 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
271 }
272 }
274 static void __serial_rx(char c, struct cpu_user_regs *regs)
275 {
276 if ( xen_rx )
277 return handle_keypress(c, regs);
279 /* Deliver input to guest buffer, unless it is already full. */
280 if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
281 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
282 /* Always notify the guest: prevents receive path from getting stuck. */
283 send_guest_global_virq(dom0, VIRQ_CONSOLE);
284 }
286 static void serial_rx(char c, struct cpu_user_regs *regs)
287 {
288 static int switch_code_count = 0;
290 if ( (SWITCH_CODE != 0) && (c == SWITCH_CODE) )
291 {
292 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
293 if ( ++switch_code_count == 3 )
294 {
295 switch_serial_input();
296 switch_code_count = 0;
297 return;
298 }
299 }
300 else
301 {
302 switch_code_count = 0;
303 }
305 /* Finally process the just-received character. */
306 __serial_rx(c, regs);
307 }
309 static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
310 {
311 char kbuf[128], *kptr;
312 int kcount;
314 while ( count > 0 )
315 {
316 while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
317 {
318 if ( hypercall_preempt_check() )
319 break;
320 cpu_relax();
321 }
323 if ( hypercall_preempt_check() )
324 return hypercall_create_continuation(
325 __HYPERVISOR_console_io, "iih",
326 CONSOLEIO_write, count, buffer);
328 kcount = min_t(int, count, sizeof(kbuf)-1);
329 if ( copy_from_guest(kbuf, buffer, kcount) )
330 return -EFAULT;
331 kbuf[kcount] = '\0';
333 sercon_puts(kbuf);
335 for ( kptr = kbuf; *kptr != '\0'; kptr++ )
336 {
337 vga_putchar(*kptr);
338 if ( opt_console_to_ring )
339 putchar_console_ring(*kptr);
340 }
342 if ( opt_console_to_ring )
343 send_guest_global_virq(dom0, VIRQ_CON_RING);
345 guest_handle_add_offset(buffer, kcount);
346 count -= kcount;
347 }
349 return 0;
350 }
352 long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
353 {
354 long rc;
355 unsigned int idx, len;
357 #ifndef VERBOSE
358 /* Only domain 0 may access the emergency console. */
359 if ( current->domain->domain_id != 0 )
360 return -EPERM;
361 #endif
363 switch ( cmd )
364 {
365 case CONSOLEIO_write:
366 rc = guest_console_write(buffer, count);
367 break;
368 case CONSOLEIO_read:
369 rc = 0;
370 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
371 {
372 idx = SERIAL_RX_MASK(serial_rx_cons);
373 len = serial_rx_prod - serial_rx_cons;
374 if ( (idx + len) > SERIAL_RX_SIZE )
375 len = SERIAL_RX_SIZE - idx;
376 if ( (rc + len) > count )
377 len = count - rc;
378 if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) )
379 {
380 rc = -EFAULT;
381 break;
382 }
383 rc += len;
384 serial_rx_cons += len;
385 }
386 break;
387 default:
388 rc = -ENOSYS;
389 break;
390 }
392 return rc;
393 }
396 /*
397 * *****************************************************
398 * *************** GENERIC CONSOLE I/O *****************
399 * *****************************************************
400 */
402 static void __putstr(const char *str)
403 {
404 int c;
406 sercon_puts(str);
408 while ( (c = *str++) != '\0' )
409 {
410 vga_putchar(c);
411 putchar_console_ring(c);
412 }
414 send_guest_global_virq(dom0, VIRQ_CON_RING);
415 }
417 static int printk_prefix_check(char *p, char **pp)
418 {
419 int loglvl = -1;
420 int upper_thresh = xenlog_upper_thresh;
421 int lower_thresh = xenlog_lower_thresh;
423 while ( (p[0] == '<') && (p[1] != '\0') && (p[2] == '>') )
424 {
425 switch ( p[1] )
426 {
427 case 'G':
428 upper_thresh = xenlog_guest_upper_thresh;
429 lower_thresh = xenlog_guest_lower_thresh;
430 if ( loglvl == -1 )
431 loglvl = XENLOG_GUEST_DEFAULT;
432 break;
433 case '0' ... '3':
434 loglvl = p[1] - '0';
435 break;
436 }
437 p += 3;
438 }
440 if ( loglvl == -1 )
441 loglvl = XENLOG_DEFAULT;
443 *pp = p;
445 return ((atomic_read(&print_everything) != 0) ||
446 (loglvl < lower_thresh) ||
447 ((loglvl < upper_thresh) && printk_ratelimit()));
448 }
450 void printk(const char *fmt, ...)
451 {
452 static char buf[1024];
453 static int start_of_line = 1, do_print;
455 va_list args;
456 char *p, *q;
457 unsigned long flags;
459 /* console_lock can be acquired recursively from __printk_ratelimit(). */
460 local_irq_save(flags);
461 spin_lock_recursive(&console_lock);
463 va_start(args, fmt);
464 (void)vsnprintf(buf, sizeof(buf), fmt, args);
465 va_end(args);
467 p = buf;
469 while ( (q = strchr(p, '\n')) != NULL )
470 {
471 *q = '\0';
472 if ( start_of_line )
473 do_print = printk_prefix_check(p, &p);
474 if ( do_print )
475 {
476 if ( start_of_line )
477 __putstr(printk_prefix);
478 __putstr(p);
479 __putstr("\n");
480 }
481 start_of_line = 1;
482 p = q + 1;
483 }
485 if ( *p != '\0' )
486 {
487 if ( start_of_line )
488 do_print = printk_prefix_check(p, &p);
489 if ( do_print )
490 {
491 if ( start_of_line )
492 __putstr(printk_prefix);
493 __putstr(p);
494 }
495 start_of_line = 0;
496 }
498 spin_unlock_recursive(&console_lock);
499 local_irq_restore(flags);
500 }
502 void set_printk_prefix(const char *prefix)
503 {
504 safe_strcpy(printk_prefix, prefix);
505 }
507 void __init init_console(void)
508 {
509 char *p;
511 /* Where should console output go? */
512 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
513 {
514 if ( *p == ',' )
515 p++;
516 if ( strncmp(p, "com", 3) == 0 )
517 sercon_handle = serial_parse_handle(p);
518 else if ( strncmp(p, "vga", 3) == 0 )
519 vga_init();
520 }
522 serial_set_rx_handler(sercon_handle, serial_rx);
524 /* HELLO WORLD --- start-of-day banner text. */
525 printk(xen_banner());
526 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
527 printk(" University of Cambridge Computer Laboratory\n\n");
528 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
529 xen_major_version(), xen_minor_version(), xen_extra_version(),
530 xen_compile_by(), xen_compile_domain(),
531 xen_compiler(), xen_compile_date());
532 printk(" Latest ChangeSet: %s\n\n", xen_changeset());
533 set_printk_prefix("(XEN) ");
535 if ( opt_sync_console )
536 {
537 serial_start_sync(sercon_handle);
538 add_taint(TAINT_SYNC_CONSOLE);
539 printk("Console output is synchronous.\n");
540 }
541 }
543 void __init console_endboot(void)
544 {
545 int i, j;
547 printk("Std. Loglevel: %s", loglvl_str(xenlog_lower_thresh));
548 if ( xenlog_upper_thresh != xenlog_lower_thresh )
549 printk(" (Rate-limited: %s)", loglvl_str(xenlog_upper_thresh));
550 printk("\nGuest Loglevel: %s", loglvl_str(xenlog_guest_lower_thresh));
551 if ( xenlog_guest_upper_thresh != xenlog_guest_lower_thresh )
552 printk(" (Rate-limited: %s)", loglvl_str(xenlog_guest_upper_thresh));
553 printk("\n");
555 if ( opt_sync_console )
556 {
557 printk("**********************************************\n");
558 printk("******* WARNING: CONSOLE OUTPUT IS SYNCHRONOUS\n");
559 printk("******* This option is intended to aid debugging "
560 "of Xen by ensuring\n");
561 printk("******* that all output is synchronously delivered "
562 "on the serial line.\n");
563 printk("******* However it can introduce SIGNIFICANT latencies "
564 "and affect\n");
565 printk("******* timekeeping. It is NOT recommended for "
566 "production use!\n");
567 printk("**********************************************\n");
568 for ( i = 0; i < 3; i++ )
569 {
570 printk("%d... ", 3-i);
571 for ( j = 0; j < 100; j++ )
572 {
573 process_pending_timers();
574 mdelay(10);
575 }
576 }
577 printk("\n");
578 }
580 vga_endboot();
582 /*
583 * If user specifies so, we fool the switch routine to redirect input
584 * straight back to Xen. I use this convoluted method so we still print
585 * a useful 'how to switch' message.
586 */
587 if ( opt_conswitch[1] == 'x' )
588 xen_rx = !xen_rx;
590 /* Serial input is directed to DOM0 by default. */
591 switch_serial_input();
592 }
594 void console_start_log_everything(void)
595 {
596 atomic_inc(&print_everything);
597 }
599 void console_end_log_everything(void)
600 {
601 atomic_dec(&print_everything);
602 }
604 void console_force_unlock(void)
605 {
606 spin_lock_init(&console_lock);
607 serial_force_unlock(sercon_handle);
608 console_start_sync();
609 }
611 void console_force_lock(void)
612 {
613 spin_lock(&console_lock);
614 }
616 void console_start_sync(void)
617 {
618 console_start_log_everything();
619 serial_start_sync(sercon_handle);
620 }
622 void console_end_sync(void)
623 {
624 serial_end_sync(sercon_handle);
625 console_end_log_everything();
626 }
628 void console_putc(char c)
629 {
630 serial_putc(sercon_handle, c);
631 }
633 int console_getc(void)
634 {
635 return serial_getc(sercon_handle);
636 }
638 /*
639 * printk rate limiting, lifted from Linux.
640 *
641 * This enforces a rate limit: not more than one kernel message
642 * every printk_ratelimit_ms (millisecs).
643 */
644 int __printk_ratelimit(int ratelimit_ms, int ratelimit_burst)
645 {
646 static DEFINE_SPINLOCK(ratelimit_lock);
647 static unsigned long toks = 10 * 5 * 1000;
648 static unsigned long last_msg;
649 static int missed;
650 unsigned long flags;
651 unsigned long long now = NOW(); /* ns */
652 unsigned long ms;
654 do_div(now, 1000000);
655 ms = (unsigned long)now;
657 spin_lock_irqsave(&ratelimit_lock, flags);
658 toks += ms - last_msg;
659 last_msg = ms;
660 if ( toks > (ratelimit_burst * ratelimit_ms))
661 toks = ratelimit_burst * ratelimit_ms;
662 if ( toks >= ratelimit_ms )
663 {
664 int lost = missed;
665 missed = 0;
666 toks -= ratelimit_ms;
667 spin_unlock(&ratelimit_lock);
668 if ( lost )
669 {
670 char lost_str[8];
671 snprintf(lost_str, sizeof(lost_str), "%d", lost);
672 /* console_lock may already be acquired by printk(). */
673 spin_lock_recursive(&console_lock);
674 __putstr(printk_prefix);
675 __putstr("printk: ");
676 __putstr(lost_str);
677 __putstr(" messages suppressed.\n");
678 spin_unlock_recursive(&console_lock);
679 }
680 local_irq_restore(flags);
681 return 1;
682 }
683 missed++;
684 spin_unlock_irqrestore(&ratelimit_lock, flags);
685 return 0;
686 }
688 /* minimum time in ms between messages */
689 int printk_ratelimit_ms = 5 * 1000;
691 /* number of messages we send before ratelimiting */
692 int printk_ratelimit_burst = 10;
694 int printk_ratelimit(void)
695 {
696 return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst);
697 }
699 /*
700 * **************************************************************
701 * *************** Serial console ring buffer *******************
702 * **************************************************************
703 */
705 #ifdef DEBUG_TRACE_DUMP
707 /* Send output direct to console, or buffer it? */
708 static volatile int debugtrace_send_to_console;
710 static char *debugtrace_buf; /* Debug-trace buffer */
711 static unsigned int debugtrace_prd; /* Producer index */
712 static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;
713 static unsigned int debugtrace_used;
714 static DEFINE_SPINLOCK(debugtrace_lock);
715 integer_param("debugtrace", debugtrace_kilobytes);
717 static void debugtrace_dump_worker(void)
718 {
719 if ( (debugtrace_bytes == 0) || !debugtrace_used )
720 return;
722 printk("debugtrace_dump() starting\n");
724 /* Print oldest portion of the ring. */
725 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
726 sercon_puts(&debugtrace_buf[debugtrace_prd]);
728 /* Print youngest portion of the ring. */
729 debugtrace_buf[debugtrace_prd] = '\0';
730 sercon_puts(&debugtrace_buf[0]);
732 memset(debugtrace_buf, '\0', debugtrace_bytes);
734 printk("debugtrace_dump() finished\n");
735 }
737 static void debugtrace_toggle(void)
738 {
739 unsigned long flags;
741 watchdog_disable();
742 spin_lock_irqsave(&debugtrace_lock, flags);
744 /*
745 * Dump the buffer *before* toggling, in case the act of dumping the
746 * buffer itself causes more printk() invocations.
747 */
748 printk("debugtrace_printk now writing to %s.\n",
749 !debugtrace_send_to_console ? "console": "buffer");
750 if ( !debugtrace_send_to_console )
751 debugtrace_dump_worker();
753 debugtrace_send_to_console = !debugtrace_send_to_console;
755 spin_unlock_irqrestore(&debugtrace_lock, flags);
756 watchdog_enable();
758 }
760 void debugtrace_dump(void)
761 {
762 unsigned long flags;
764 watchdog_disable();
765 spin_lock_irqsave(&debugtrace_lock, flags);
767 debugtrace_dump_worker();
769 spin_unlock_irqrestore(&debugtrace_lock, flags);
770 watchdog_enable();
771 }
773 void debugtrace_printk(const char *fmt, ...)
774 {
775 static char buf[1024];
776 static u32 count;
778 va_list args;
779 char *p;
780 unsigned long flags;
782 if ( debugtrace_bytes == 0 )
783 return;
785 debugtrace_used = 1;
787 spin_lock_irqsave(&debugtrace_lock, flags);
789 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
791 snprintf(buf, sizeof(buf), "%u ", ++count);
793 va_start(args, fmt);
794 (void)vsnprintf(buf + strlen(buf), sizeof(buf), fmt, args);
795 va_end(args);
797 if ( debugtrace_send_to_console )
798 {
799 serial_puts(sercon_handle, buf);
800 }
801 else
802 {
803 for ( p = buf; *p != '\0'; p++ )
804 {
805 debugtrace_buf[debugtrace_prd++] = *p;
806 /* Always leave a nul byte at the end of the buffer. */
807 if ( debugtrace_prd == (debugtrace_bytes - 1) )
808 debugtrace_prd = 0;
809 }
810 }
812 spin_unlock_irqrestore(&debugtrace_lock, flags);
813 }
815 static void debugtrace_key(unsigned char key)
816 {
817 debugtrace_toggle();
818 }
820 static int __init debugtrace_init(void)
821 {
822 int order;
823 unsigned int kbytes, bytes;
825 /* Round size down to next power of two. */
826 while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 )
827 debugtrace_kilobytes = kbytes;
829 bytes = debugtrace_kilobytes << 10;
830 if ( bytes == 0 )
831 return 0;
833 order = get_order_from_bytes(bytes);
834 debugtrace_buf = alloc_xenheap_pages(order);
835 ASSERT(debugtrace_buf != NULL);
837 memset(debugtrace_buf, '\0', bytes);
839 debugtrace_bytes = bytes;
841 register_keyhandler(
842 'T', debugtrace_key, "toggle debugtrace to console/buffer");
844 return 0;
845 }
846 __initcall(debugtrace_init);
848 #endif /* !NDEBUG */
851 /*
852 * **************************************************************
853 * *************** Debugging/tracing/error-report ***************
854 * **************************************************************
855 */
857 void panic(const char *fmt, ...)
858 {
859 va_list args;
860 unsigned long flags;
861 static DEFINE_SPINLOCK(lock);
862 static char buf[128];
864 debugtrace_dump();
866 /* Protects buf[] and ensure multi-line message prints atomically. */
867 spin_lock_irqsave(&lock, flags);
869 va_start(args, fmt);
870 (void)vsnprintf(buf, sizeof(buf), fmt, args);
871 va_end(args);
873 console_start_sync();
874 printk("\n****************************************\n");
875 printk("Panic on CPU %d:\n", smp_processor_id());
876 printk(buf);
877 printk("****************************************\n\n");
878 if ( opt_noreboot )
879 printk("Manual reset required ('noreboot' specified)\n");
880 else
881 printk("Reboot in five seconds...\n");
883 spin_unlock_irqrestore(&lock, flags);
885 debugger_trap_immediate();
887 kexec_crash();
889 if ( opt_noreboot )
890 {
891 machine_halt();
892 }
893 else
894 {
895 watchdog_disable();
896 mdelay(5000);
897 machine_restart(NULL);
898 }
899 }
901 void __bug(char *file, int line)
902 {
903 console_start_sync();
904 printk("Xen BUG at %s:%d\n", file, line);
905 dump_execution_state();
906 panic("Xen BUG at %s:%d\n", file, line);
907 for ( ; ; ) ;
908 }
910 void __warn(char *file, int line)
911 {
912 printk("Xen WARN at %s:%d\n", file, line);
913 dump_execution_state();
914 }
917 /*
918 * **************************************************************
919 * ****************** Console suspend/resume ********************
920 * **************************************************************
921 */
923 static void suspend_steal_fn(const char *str) { }
924 static int suspend_steal_id;
926 int console_suspend(void)
927 {
928 suspend_steal_id = console_steal(sercon_handle, suspend_steal_fn);
929 serial_suspend();
930 return 0;
931 }
933 int console_resume(void)
934 {
935 serial_resume();
936 console_giveback(suspend_steal_id);
937 return 0;
938 }
940 /*
941 * Local variables:
942 * mode: C
943 * c-set-style: "BSD"
944 * c-basic-offset: 4
945 * tab-width: 4
946 * indent-tabs-mode: nil
947 * End:
948 */