ia64/xen-unstable

view xen/drivers/char/console.c @ 15896:42d4313b5fdd

[IA64] update .hgignore for xenitp

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author Alex Williamson <alex.williamson@hp.com>
date Mon Sep 24 14:21:02 2007 -0600 (2007-09-24)
parents 1c85fe14169f
children 66fa2bc70e2a
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>
35 #include <xsm/xsm.h>
37 /* console: comma-separated list of console outputs. */
38 static char opt_console[30] = OPT_CONSOLE_STR;
39 string_param("console", opt_console);
41 /* conswitch: a character pair controlling console switching. */
42 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
43 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
44 /* boots. Any other value, or omitting the char, enables auto-switch */
45 static unsigned char opt_conswitch[5] = "a";
46 string_param("conswitch", opt_conswitch);
48 /* sync_console: force synchronous console output (useful for debugging). */
49 static int opt_sync_console;
50 boolean_param("sync_console", opt_sync_console);
52 /* console_to_ring: send guest (incl. dom 0) console data to console ring. */
53 static int opt_console_to_ring;
54 boolean_param("console_to_ring", opt_console_to_ring);
56 #define CONRING_SIZE 16384
57 #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
58 static char conring[CONRING_SIZE];
59 static unsigned int conringc, conringp;
61 static char printk_prefix[16] = "";
63 static int sercon_handle = -1;
65 static DEFINE_SPINLOCK(console_lock);
67 /*
68 * To control the amount of printing, thresholds are added.
69 * These thresholds correspond to the XENLOG logging levels.
70 * There's an upper and lower threshold for non-guest messages and for
71 * guest-provoked messages. This works as follows, for a given log level L:
72 *
73 * L < lower_threshold : always logged
74 * lower_threshold <= L < upper_threshold : rate-limited logging
75 * upper_threshold <= L : never logged
76 *
77 * Note, in the above algorithm, to disable rate limiting simply make
78 * the lower threshold equal to the upper.
79 */
80 #ifdef NDEBUG
81 #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
82 #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */
83 #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
84 #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */
85 #else
86 #define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */
87 #define XENLOG_LOWER_THRESHOLD 4 /* Print everything */
88 #define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */
89 #define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */
90 #endif
91 /*
92 * The XENLOG_DEFAULT is the default given to printks that
93 * do not have any print level associated with them.
94 */
95 #define XENLOG_DEFAULT 1 /* XENLOG_WARNING */
96 #define XENLOG_GUEST_DEFAULT 1 /* XENLOG_WARNING */
98 static int xenlog_upper_thresh = XENLOG_UPPER_THRESHOLD;
99 static int xenlog_lower_thresh = XENLOG_LOWER_THRESHOLD;
100 static int xenlog_guest_upper_thresh = XENLOG_GUEST_UPPER_THRESHOLD;
101 static int xenlog_guest_lower_thresh = XENLOG_GUEST_LOWER_THRESHOLD;
103 static void parse_loglvl(char *s);
104 static void parse_guest_loglvl(char *s);
106 /*
107 * <lvl> := none|error|warning|info|debug|all
108 * loglvl=<lvl_print_always>[/<lvl_print_ratelimit>]
109 * <lvl_print_always>: log level which is always printed
110 * <lvl_print_rlimit>: log level which is rate-limit printed
111 * Similar definitions for guest_loglvl, but applies to guest tracing.
112 * Defaults: loglvl=warning ; guest_loglvl=none/warning
113 */
114 custom_param("loglvl", parse_loglvl);
115 custom_param("guest_loglvl", parse_guest_loglvl);
117 static atomic_t print_everything = ATOMIC_INIT(0);
119 #define ___parse_loglvl(s, ps, lvlstr, lvlnum) \
120 if ( !strncmp((s), (lvlstr), strlen(lvlstr)) ) { \
121 *(ps) = (s) + strlen(lvlstr); \
122 return (lvlnum); \
123 }
125 static int __init __parse_loglvl(char *s, char **ps)
126 {
127 ___parse_loglvl(s, ps, "none", 0);
128 ___parse_loglvl(s, ps, "error", 1);
129 ___parse_loglvl(s, ps, "warning", 2);
130 ___parse_loglvl(s, ps, "info", 3);
131 ___parse_loglvl(s, ps, "debug", 4);
132 ___parse_loglvl(s, ps, "all", 4);
133 return 2; /* sane fallback */
134 }
136 static void __init _parse_loglvl(char *s, int *lower, int *upper)
137 {
138 *lower = *upper = __parse_loglvl(s, &s);
139 if ( *s == '/' )
140 *upper = __parse_loglvl(s+1, &s);
141 if ( *upper < *lower )
142 *upper = *lower;
143 }
145 static void __init parse_loglvl(char *s)
146 {
147 _parse_loglvl(s, &xenlog_lower_thresh, &xenlog_upper_thresh);
148 }
150 static void __init parse_guest_loglvl(char *s)
151 {
152 _parse_loglvl(s, &xenlog_guest_lower_thresh, &xenlog_guest_upper_thresh);
153 }
155 static char * __init loglvl_str(int lvl)
156 {
157 switch ( lvl )
158 {
159 case 0: return "Nothing";
160 case 1: return "Errors";
161 case 2: return "Errors and warnings";
162 case 3: return "Errors, warnings and info";
163 case 4: return "All";
164 }
165 return "???";
166 }
168 /*
169 * ********************************************************
170 * *************** ACCESS TO CONSOLE RING *****************
171 * ********************************************************
172 */
174 static void putchar_console_ring(int c)
175 {
176 conring[CONRING_IDX_MASK(conringp++)] = c;
177 if ( (conringp - conringc) > CONRING_SIZE )
178 conringc = conringp - CONRING_SIZE;
179 }
181 long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear)
182 {
183 unsigned int idx, len, max, sofar, c;
184 unsigned long flags;
186 max = *pcount;
187 sofar = 0;
189 c = conringc;
190 while ( (c != conringp) && (sofar < max) )
191 {
192 idx = CONRING_IDX_MASK(c);
193 len = conringp - c;
194 if ( (idx + len) > CONRING_SIZE )
195 len = CONRING_SIZE - idx;
196 if ( (sofar + len) > max )
197 len = max - sofar;
198 if ( copy_to_guest_offset(str, sofar, &conring[idx], len) )
199 return -EFAULT;
200 sofar += len;
201 c += len;
202 }
204 if ( clear )
205 {
206 spin_lock_irqsave(&console_lock, flags);
207 if ( (conringp - c) > CONRING_SIZE )
208 conringc = conringp - CONRING_SIZE;
209 else
210 conringc = c;
211 spin_unlock_irqrestore(&console_lock, flags);
212 }
214 *pcount = sofar;
215 return 0;
216 }
219 /*
220 * *******************************************************
221 * *************** ACCESS TO SERIAL LINE *****************
222 * *******************************************************
223 */
225 /* Characters received over the serial line are buffered for domain 0. */
226 #define SERIAL_RX_SIZE 128
227 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
228 static char serial_rx_ring[SERIAL_RX_SIZE];
229 static unsigned int serial_rx_cons, serial_rx_prod;
231 static void (*serial_steal_fn)(const char *);
233 int console_steal(int handle, void (*fn)(const char *))
234 {
235 if ( (handle == -1) || (handle != sercon_handle) )
236 return 0;
238 if ( serial_steal_fn != NULL )
239 return -EBUSY;
241 serial_steal_fn = fn;
242 return 1;
243 }
245 void console_giveback(int id)
246 {
247 if ( id == 1 )
248 serial_steal_fn = NULL;
249 }
251 static void sercon_puts(const char *s)
252 {
253 if ( serial_steal_fn != NULL )
254 (*serial_steal_fn)(s);
255 else
256 serial_puts(sercon_handle, s);
257 }
259 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
260 #define SWITCH_CODE (opt_conswitch[0]-'a'+1)
261 static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
263 static void switch_serial_input(void)
264 {
265 static char *input_str[2] = { "DOM0", "Xen" };
266 xen_rx = !xen_rx;
267 if ( (SWITCH_CODE != 0) && (dom0 != NULL) )
268 {
269 printk("*** Serial input -> %s "
270 "(type 'CTRL-%c' three times to switch input to %s).\n",
271 input_str[xen_rx], opt_conswitch[0], input_str[!xen_rx]);
272 }
273 }
275 static void __serial_rx(char c, struct cpu_user_regs *regs)
276 {
277 if ( xen_rx )
278 return handle_keypress(c, regs);
280 /* Deliver input to guest buffer, unless it is already full. */
281 if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
282 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
283 /* Always notify the guest: prevents receive path from getting stuck. */
284 send_guest_global_virq(dom0, VIRQ_CONSOLE);
285 }
287 static void serial_rx(char c, struct cpu_user_regs *regs)
288 {
289 static int switch_code_count = 0;
291 if ( (SWITCH_CODE != 0) && (c == SWITCH_CODE) )
292 {
293 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
294 if ( ++switch_code_count == 3 )
295 {
296 switch_serial_input();
297 switch_code_count = 0;
298 return;
299 }
300 }
301 else
302 {
303 switch_code_count = 0;
304 }
306 /* Finally process the just-received character. */
307 __serial_rx(c, regs);
308 }
310 static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
311 {
312 char kbuf[128], *kptr;
313 int kcount;
315 while ( count > 0 )
316 {
317 while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
318 {
319 if ( hypercall_preempt_check() )
320 break;
321 cpu_relax();
322 }
324 if ( hypercall_preempt_check() )
325 return hypercall_create_continuation(
326 __HYPERVISOR_console_io, "iih",
327 CONSOLEIO_write, count, buffer);
329 kcount = min_t(int, count, sizeof(kbuf)-1);
330 if ( copy_from_guest(kbuf, buffer, kcount) )
331 return -EFAULT;
332 kbuf[kcount] = '\0';
334 sercon_puts(kbuf);
335 vga_puts(kbuf);
337 if ( opt_console_to_ring )
338 for ( kptr = kbuf; *kptr != '\0'; kptr++ )
339 putchar_console_ring(*kptr);
341 if ( opt_console_to_ring )
342 send_guest_global_virq(dom0, VIRQ_CON_RING);
344 guest_handle_add_offset(buffer, kcount);
345 count -= kcount;
346 }
348 return 0;
349 }
351 long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
352 {
353 long rc;
354 unsigned int idx, len;
356 #ifndef VERBOSE
357 /* Only domain 0 may access the emergency console. */
358 if ( current->domain->domain_id != 0 )
359 return -EPERM;
360 #endif
362 rc = xsm_console_io(current->domain, cmd);
363 if ( rc )
364 return rc;
366 switch ( cmd )
367 {
368 case CONSOLEIO_write:
369 rc = guest_console_write(buffer, count);
370 break;
371 case CONSOLEIO_read:
372 rc = 0;
373 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
374 {
375 idx = SERIAL_RX_MASK(serial_rx_cons);
376 len = serial_rx_prod - serial_rx_cons;
377 if ( (idx + len) > SERIAL_RX_SIZE )
378 len = SERIAL_RX_SIZE - idx;
379 if ( (rc + len) > count )
380 len = count - rc;
381 if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) )
382 {
383 rc = -EFAULT;
384 break;
385 }
386 rc += len;
387 serial_rx_cons += len;
388 }
389 break;
390 default:
391 rc = -ENOSYS;
392 break;
393 }
395 return rc;
396 }
399 /*
400 * *****************************************************
401 * *************** GENERIC CONSOLE I/O *****************
402 * *****************************************************
403 */
405 static void __putstr(const char *str)
406 {
407 int c;
409 sercon_puts(str);
410 vga_puts(str);
412 while ( (c = *str++) != '\0' )
413 putchar_console_ring(c);
415 send_guest_global_virq(dom0, VIRQ_CON_RING);
416 }
418 static int printk_prefix_check(char *p, char **pp)
419 {
420 int loglvl = -1;
421 int upper_thresh = xenlog_upper_thresh;
422 int lower_thresh = xenlog_lower_thresh;
424 while ( (p[0] == '<') && (p[1] != '\0') && (p[2] == '>') )
425 {
426 switch ( p[1] )
427 {
428 case 'G':
429 upper_thresh = xenlog_guest_upper_thresh;
430 lower_thresh = xenlog_guest_lower_thresh;
431 if ( loglvl == -1 )
432 loglvl = XENLOG_GUEST_DEFAULT;
433 break;
434 case '0' ... '3':
435 loglvl = p[1] - '0';
436 break;
437 }
438 p += 3;
439 }
441 if ( loglvl == -1 )
442 loglvl = XENLOG_DEFAULT;
444 *pp = p;
446 return ((atomic_read(&print_everything) != 0) ||
447 (loglvl < lower_thresh) ||
448 ((loglvl < upper_thresh) && printk_ratelimit()));
449 }
451 void printk(const char *fmt, ...)
452 {
453 static char buf[1024];
454 static int start_of_line = 1, do_print;
456 va_list args;
457 char *p, *q;
458 unsigned long flags;
460 /* console_lock can be acquired recursively from __printk_ratelimit(). */
461 local_irq_save(flags);
462 spin_lock_recursive(&console_lock);
464 va_start(args, fmt);
465 (void)vsnprintf(buf, sizeof(buf), fmt, args);
466 va_end(args);
468 p = buf;
470 while ( (q = strchr(p, '\n')) != NULL )
471 {
472 *q = '\0';
473 if ( start_of_line )
474 do_print = printk_prefix_check(p, &p);
475 if ( do_print )
476 {
477 if ( start_of_line )
478 __putstr(printk_prefix);
479 __putstr(p);
480 __putstr("\n");
481 }
482 start_of_line = 1;
483 p = q + 1;
484 }
486 if ( *p != '\0' )
487 {
488 if ( start_of_line )
489 do_print = printk_prefix_check(p, &p);
490 if ( do_print )
491 {
492 if ( start_of_line )
493 __putstr(printk_prefix);
494 __putstr(p);
495 }
496 start_of_line = 0;
497 }
499 spin_unlock_recursive(&console_lock);
500 local_irq_restore(flags);
501 }
503 void set_printk_prefix(const char *prefix)
504 {
505 safe_strcpy(printk_prefix, prefix);
506 }
508 void __init init_console(void)
509 {
510 char *p;
512 /* Where should console output go? */
513 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
514 {
515 if ( *p == ',' )
516 p++;
517 if ( strncmp(p, "com", 3) == 0 )
518 sercon_handle = serial_parse_handle(p);
519 else if ( strncmp(p, "vga", 3) == 0 )
520 vga_init();
521 }
523 serial_set_rx_handler(sercon_handle, serial_rx);
525 /* HELLO WORLD --- start-of-day banner text. */
526 printk(xen_banner());
527 printk(" http://www.cl.cam.ac.uk/netos/xen\n");
528 printk(" University of Cambridge Computer Laboratory\n\n");
529 printk(" Xen version %d.%d%s (%s@%s) (%s) %s\n",
530 xen_major_version(), xen_minor_version(), xen_extra_version(),
531 xen_compile_by(), xen_compile_domain(),
532 xen_compiler(), xen_compile_date());
533 printk(" Latest ChangeSet: %s\n\n", xen_changeset());
534 set_printk_prefix("(XEN) ");
536 if ( opt_sync_console )
537 {
538 serial_start_sync(sercon_handle);
539 add_taint(TAINT_SYNC_CONSOLE);
540 printk("Console output is synchronous.\n");
541 }
542 }
544 void __init console_endboot(void)
545 {
546 int i, j;
548 printk("Std. Loglevel: %s", loglvl_str(xenlog_lower_thresh));
549 if ( xenlog_upper_thresh != xenlog_lower_thresh )
550 printk(" (Rate-limited: %s)", loglvl_str(xenlog_upper_thresh));
551 printk("\nGuest Loglevel: %s", loglvl_str(xenlog_guest_lower_thresh));
552 if ( xenlog_guest_upper_thresh != xenlog_guest_lower_thresh )
553 printk(" (Rate-limited: %s)", loglvl_str(xenlog_guest_upper_thresh));
554 printk("\n");
556 if ( opt_sync_console )
557 {
558 printk("**********************************************\n");
559 printk("******* WARNING: CONSOLE OUTPUT IS SYNCHRONOUS\n");
560 printk("******* This option is intended to aid debugging "
561 "of Xen by ensuring\n");
562 printk("******* that all output is synchronously delivered "
563 "on the serial line.\n");
564 printk("******* However it can introduce SIGNIFICANT latencies "
565 "and affect\n");
566 printk("******* timekeeping. It is NOT recommended for "
567 "production use!\n");
568 printk("**********************************************\n");
569 for ( i = 0; i < 3; i++ )
570 {
571 printk("%d... ", 3-i);
572 for ( j = 0; j < 100; j++ )
573 {
574 process_pending_timers();
575 mdelay(10);
576 }
577 }
578 printk("\n");
579 }
581 vga_endboot();
583 /*
584 * If user specifies so, we fool the switch routine to redirect input
585 * straight back to Xen. I use this convoluted method so we still print
586 * a useful 'how to switch' message.
587 */
588 if ( opt_conswitch[1] == 'x' )
589 xen_rx = !xen_rx;
591 /* Serial input is directed to DOM0 by default. */
592 switch_serial_input();
593 }
595 void console_start_log_everything(void)
596 {
597 atomic_inc(&print_everything);
598 }
600 void console_end_log_everything(void)
601 {
602 atomic_dec(&print_everything);
603 }
605 void console_force_unlock(void)
606 {
607 spin_lock_init(&console_lock);
608 serial_force_unlock(sercon_handle);
609 console_start_sync();
610 }
612 void console_force_lock(void)
613 {
614 spin_lock(&console_lock);
615 }
617 void console_start_sync(void)
618 {
619 console_start_log_everything();
620 serial_start_sync(sercon_handle);
621 }
623 void console_end_sync(void)
624 {
625 serial_end_sync(sercon_handle);
626 console_end_log_everything();
627 }
629 void console_putc(char c)
630 {
631 serial_putc(sercon_handle, c);
632 }
634 int console_getc(void)
635 {
636 return serial_getc(sercon_handle);
637 }
639 /*
640 * printk rate limiting, lifted from Linux.
641 *
642 * This enforces a rate limit: not more than one kernel message
643 * every printk_ratelimit_ms (millisecs).
644 */
645 int __printk_ratelimit(int ratelimit_ms, int ratelimit_burst)
646 {
647 static DEFINE_SPINLOCK(ratelimit_lock);
648 static unsigned long toks = 10 * 5 * 1000;
649 static unsigned long last_msg;
650 static int missed;
651 unsigned long flags;
652 unsigned long long now = NOW(); /* ns */
653 unsigned long ms;
655 do_div(now, 1000000);
656 ms = (unsigned long)now;
658 spin_lock_irqsave(&ratelimit_lock, flags);
659 toks += ms - last_msg;
660 last_msg = ms;
661 if ( toks > (ratelimit_burst * ratelimit_ms))
662 toks = ratelimit_burst * ratelimit_ms;
663 if ( toks >= ratelimit_ms )
664 {
665 int lost = missed;
666 missed = 0;
667 toks -= ratelimit_ms;
668 spin_unlock(&ratelimit_lock);
669 if ( lost )
670 {
671 char lost_str[8];
672 snprintf(lost_str, sizeof(lost_str), "%d", lost);
673 /* console_lock may already be acquired by printk(). */
674 spin_lock_recursive(&console_lock);
675 __putstr(printk_prefix);
676 __putstr("printk: ");
677 __putstr(lost_str);
678 __putstr(" messages suppressed.\n");
679 spin_unlock_recursive(&console_lock);
680 }
681 local_irq_restore(flags);
682 return 1;
683 }
684 missed++;
685 spin_unlock_irqrestore(&ratelimit_lock, flags);
686 return 0;
687 }
689 /* minimum time in ms between messages */
690 int printk_ratelimit_ms = 5 * 1000;
692 /* number of messages we send before ratelimiting */
693 int printk_ratelimit_burst = 10;
695 int printk_ratelimit(void)
696 {
697 return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst);
698 }
700 /*
701 * **************************************************************
702 * *************** Serial console ring buffer *******************
703 * **************************************************************
704 */
706 #ifdef DEBUG_TRACE_DUMP
708 /* Send output direct to console, or buffer it? */
709 static volatile int debugtrace_send_to_console;
711 static char *debugtrace_buf; /* Debug-trace buffer */
712 static unsigned int debugtrace_prd; /* Producer index */
713 static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;
714 static unsigned int debugtrace_used;
715 static DEFINE_SPINLOCK(debugtrace_lock);
716 integer_param("debugtrace", debugtrace_kilobytes);
718 static void debugtrace_dump_worker(void)
719 {
720 if ( (debugtrace_bytes == 0) || !debugtrace_used )
721 return;
723 printk("debugtrace_dump() starting\n");
725 /* Print oldest portion of the ring. */
726 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
727 sercon_puts(&debugtrace_buf[debugtrace_prd]);
729 /* Print youngest portion of the ring. */
730 debugtrace_buf[debugtrace_prd] = '\0';
731 sercon_puts(&debugtrace_buf[0]);
733 memset(debugtrace_buf, '\0', debugtrace_bytes);
735 printk("debugtrace_dump() finished\n");
736 }
738 static void debugtrace_toggle(void)
739 {
740 unsigned long flags;
742 watchdog_disable();
743 spin_lock_irqsave(&debugtrace_lock, flags);
745 /*
746 * Dump the buffer *before* toggling, in case the act of dumping the
747 * buffer itself causes more printk() invocations.
748 */
749 printk("debugtrace_printk now writing to %s.\n",
750 !debugtrace_send_to_console ? "console": "buffer");
751 if ( !debugtrace_send_to_console )
752 debugtrace_dump_worker();
754 debugtrace_send_to_console = !debugtrace_send_to_console;
756 spin_unlock_irqrestore(&debugtrace_lock, flags);
757 watchdog_enable();
759 }
761 void debugtrace_dump(void)
762 {
763 unsigned long flags;
765 watchdog_disable();
766 spin_lock_irqsave(&debugtrace_lock, flags);
768 debugtrace_dump_worker();
770 spin_unlock_irqrestore(&debugtrace_lock, flags);
771 watchdog_enable();
772 }
774 void debugtrace_printk(const char *fmt, ...)
775 {
776 static char buf[1024];
777 static u32 count;
779 va_list args;
780 char *p;
781 unsigned long flags;
783 if ( debugtrace_bytes == 0 )
784 return;
786 debugtrace_used = 1;
788 spin_lock_irqsave(&debugtrace_lock, flags);
790 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
792 snprintf(buf, sizeof(buf), "%u ", ++count);
794 va_start(args, fmt);
795 (void)vsnprintf(buf + strlen(buf), sizeof(buf), fmt, args);
796 va_end(args);
798 if ( debugtrace_send_to_console )
799 {
800 serial_puts(sercon_handle, buf);
801 }
802 else
803 {
804 for ( p = buf; *p != '\0'; p++ )
805 {
806 debugtrace_buf[debugtrace_prd++] = *p;
807 /* Always leave a nul byte at the end of the buffer. */
808 if ( debugtrace_prd == (debugtrace_bytes - 1) )
809 debugtrace_prd = 0;
810 }
811 }
813 spin_unlock_irqrestore(&debugtrace_lock, flags);
814 }
816 static void debugtrace_key(unsigned char key)
817 {
818 debugtrace_toggle();
819 }
821 static int __init debugtrace_init(void)
822 {
823 int order;
824 unsigned int kbytes, bytes;
826 /* Round size down to next power of two. */
827 while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 )
828 debugtrace_kilobytes = kbytes;
830 bytes = debugtrace_kilobytes << 10;
831 if ( bytes == 0 )
832 return 0;
834 order = get_order_from_bytes(bytes);
835 debugtrace_buf = alloc_xenheap_pages(order);
836 ASSERT(debugtrace_buf != NULL);
838 memset(debugtrace_buf, '\0', bytes);
840 debugtrace_bytes = bytes;
842 register_keyhandler(
843 'T', debugtrace_key, "toggle debugtrace to console/buffer");
845 return 0;
846 }
847 __initcall(debugtrace_init);
849 #endif /* !NDEBUG */
852 /*
853 * **************************************************************
854 * *************** Debugging/tracing/error-report ***************
855 * **************************************************************
856 */
858 void panic(const char *fmt, ...)
859 {
860 va_list args;
861 unsigned long flags;
862 static DEFINE_SPINLOCK(lock);
863 static char buf[128];
865 debugtrace_dump();
867 /* Protects buf[] and ensure multi-line message prints atomically. */
868 spin_lock_irqsave(&lock, flags);
870 va_start(args, fmt);
871 (void)vsnprintf(buf, sizeof(buf), fmt, args);
872 va_end(args);
874 console_start_sync();
875 printk("\n****************************************\n");
876 printk("Panic on CPU %d:\n", smp_processor_id());
877 printk(buf);
878 printk("****************************************\n\n");
879 if ( opt_noreboot )
880 printk("Manual reset required ('noreboot' specified)\n");
881 else
882 printk("Reboot in five seconds...\n");
884 spin_unlock_irqrestore(&lock, flags);
886 debugger_trap_immediate();
888 kexec_crash();
890 if ( opt_noreboot )
891 {
892 machine_halt();
893 }
894 else
895 {
896 watchdog_disable();
897 mdelay(5000);
898 machine_restart();
899 }
900 }
902 void __bug(char *file, int line)
903 {
904 console_start_sync();
905 printk("Xen BUG at %s:%d\n", file, line);
906 dump_execution_state();
907 panic("Xen BUG at %s:%d\n", file, line);
908 for ( ; ; ) ;
909 }
911 void __warn(char *file, int line)
912 {
913 printk("Xen WARN at %s:%d\n", file, line);
914 dump_execution_state();
915 }
918 /*
919 * **************************************************************
920 * ****************** Console suspend/resume ********************
921 * **************************************************************
922 */
924 static void suspend_steal_fn(const char *str) { }
925 static int suspend_steal_id;
927 int console_suspend(void)
928 {
929 suspend_steal_id = console_steal(sercon_handle, suspend_steal_fn);
930 serial_suspend();
931 return 0;
932 }
934 int console_resume(void)
935 {
936 serial_resume();
937 console_giveback(suspend_steal_id);
938 return 0;
939 }
941 /*
942 * Local variables:
943 * mode: C
944 * c-set-style: "BSD"
945 * c-basic-offset: 4
946 * tab-width: 4
947 * indent-tabs-mode: nil
948 * End:
949 */