debuggers.hg

view xen/drivers/char/console.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents e8acb9753ff1
children 700ac6445812
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/tasklet.h>
25 #include <xen/keyhandler.h>
26 #include <xen/mm.h>
27 #include <xen/delay.h>
28 #include <xen/guest_access.h>
29 #include <xen/shutdown.h>
30 #include <xen/vga.h>
31 #include <xen/kexec.h>
32 #include <asm/current.h>
33 #include <asm/debugger.h>
34 #include <asm/io.h>
35 #include <asm/div64.h>
36 #include <xsm/xsm.h>
37 #include <public/sysctl.h>
38 #include <xen/hypercall.h> /* for do_console_io */
40 /* console: comma-separated list of console outputs. */
41 static char __initdata opt_console[30] = OPT_CONSOLE_STR;
42 string_param("console", opt_console);
44 /* conswitch: a character pair controlling console switching. */
45 /* Char 1: CTRL+<char1> is used to switch console input between Xen and DOM0 */
46 /* Char 2: If this character is 'x', then do not auto-switch to DOM0 when it */
47 /* boots. Any other value, or omitting the char, enables auto-switch */
48 static unsigned char __read_mostly opt_conswitch[3] = "a";
49 string_param("conswitch", opt_conswitch);
51 /* sync_console: force synchronous console output (useful for debugging). */
52 static bool_t __initdata opt_sync_console;
53 boolean_param("sync_console", opt_sync_console);
55 /* console_to_ring: send guest (incl. dom 0) console data to console ring. */
56 static bool_t __read_mostly opt_console_to_ring;
57 boolean_param("console_to_ring", opt_console_to_ring);
59 /* console_timestamps: include a timestamp prefix on every Xen console line. */
60 static bool_t __read_mostly opt_console_timestamps;
61 boolean_param("console_timestamps", opt_console_timestamps);
63 /* conring_size: allows a large console ring than default (16kB). */
64 static uint32_t __initdata opt_conring_size;
65 size_param("conring_size", opt_conring_size);
67 #define _CONRING_SIZE 16384
68 #define CONRING_IDX_MASK(i) ((i)&(conring_size-1))
69 static char __initdata _conring[_CONRING_SIZE];
70 static char *__read_mostly conring = _conring;
71 static uint32_t __read_mostly conring_size = _CONRING_SIZE;
72 static uint32_t conringc, conringp;
74 static int __read_mostly sercon_handle = -1;
76 static DEFINE_SPINLOCK(console_lock);
78 /*
79 * To control the amount of printing, thresholds are added.
80 * These thresholds correspond to the XENLOG logging levels.
81 * There's an upper and lower threshold for non-guest messages and for
82 * guest-provoked messages. This works as follows, for a given log level L:
83 *
84 * L < lower_threshold : always logged
85 * lower_threshold <= L < upper_threshold : rate-limited logging
86 * upper_threshold <= L : never logged
87 *
88 * Note, in the above algorithm, to disable rate limiting simply make
89 * the lower threshold equal to the upper.
90 */
91 #ifdef NDEBUG
92 #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
93 #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */
94 #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */
95 #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */
96 #else
97 #define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */
98 #define XENLOG_LOWER_THRESHOLD 4 /* Print everything */
99 #define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */
100 #define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */
101 #endif
102 /*
103 * The XENLOG_DEFAULT is the default given to printks that
104 * do not have any print level associated with them.
105 */
106 #define XENLOG_DEFAULT 1 /* XENLOG_WARNING */
107 #define XENLOG_GUEST_DEFAULT 1 /* XENLOG_WARNING */
109 static int __read_mostly xenlog_upper_thresh = XENLOG_UPPER_THRESHOLD;
110 static int __read_mostly xenlog_lower_thresh = XENLOG_LOWER_THRESHOLD;
111 static int __read_mostly xenlog_guest_upper_thresh = XENLOG_GUEST_UPPER_THRESHOLD;
112 static int __read_mostly xenlog_guest_lower_thresh = XENLOG_GUEST_LOWER_THRESHOLD;
114 static void parse_loglvl(char *s);
115 static void parse_guest_loglvl(char *s);
117 /*
118 * <lvl> := none|error|warning|info|debug|all
119 * loglvl=<lvl_print_always>[/<lvl_print_ratelimit>]
120 * <lvl_print_always>: log level which is always printed
121 * <lvl_print_rlimit>: log level which is rate-limit printed
122 * Similar definitions for guest_loglvl, but applies to guest tracing.
123 * Defaults: loglvl=warning ; guest_loglvl=none/warning
124 */
125 custom_param("loglvl", parse_loglvl);
126 custom_param("guest_loglvl", parse_guest_loglvl);
128 static atomic_t print_everything = ATOMIC_INIT(0);
130 #define ___parse_loglvl(s, ps, lvlstr, lvlnum) \
131 if ( !strncmp((s), (lvlstr), strlen(lvlstr)) ) { \
132 *(ps) = (s) + strlen(lvlstr); \
133 return (lvlnum); \
134 }
136 static int __init __parse_loglvl(char *s, char **ps)
137 {
138 ___parse_loglvl(s, ps, "none", 0);
139 ___parse_loglvl(s, ps, "error", 1);
140 ___parse_loglvl(s, ps, "warning", 2);
141 ___parse_loglvl(s, ps, "info", 3);
142 ___parse_loglvl(s, ps, "debug", 4);
143 ___parse_loglvl(s, ps, "all", 4);
144 return 2; /* sane fallback */
145 }
147 static void __init _parse_loglvl(char *s, int *lower, int *upper)
148 {
149 *lower = *upper = __parse_loglvl(s, &s);
150 if ( *s == '/' )
151 *upper = __parse_loglvl(s+1, &s);
152 if ( *upper < *lower )
153 *upper = *lower;
154 }
156 static void __init parse_loglvl(char *s)
157 {
158 _parse_loglvl(s, &xenlog_lower_thresh, &xenlog_upper_thresh);
159 }
161 static void __init parse_guest_loglvl(char *s)
162 {
163 _parse_loglvl(s, &xenlog_guest_lower_thresh, &xenlog_guest_upper_thresh);
164 }
166 static char * __init loglvl_str(int lvl)
167 {
168 switch ( lvl )
169 {
170 case 0: return "Nothing";
171 case 1: return "Errors";
172 case 2: return "Errors and warnings";
173 case 3: return "Errors, warnings and info";
174 case 4: return "All";
175 }
176 return "???";
177 }
179 /*
180 * ********************************************************
181 * *************** ACCESS TO CONSOLE RING *****************
182 * ********************************************************
183 */
185 static void putchar_console_ring(int c)
186 {
187 ASSERT(spin_is_locked(&console_lock));
188 conring[CONRING_IDX_MASK(conringp++)] = c;
189 if ( (uint32_t)(conringp - conringc) > conring_size )
190 conringc = conringp - conring_size;
191 }
193 long read_console_ring(struct xen_sysctl_readconsole *op)
194 {
195 XEN_GUEST_HANDLE(char) str;
196 uint32_t idx, len, max, sofar, c;
198 str = guest_handle_cast(op->buffer, char),
199 max = op->count;
200 sofar = 0;
202 c = conringc;
203 if ( op->incremental && ((int32_t)(op->index - c) > 0) )
204 c = op->index;
206 while ( (c != conringp) && (sofar < max) )
207 {
208 idx = CONRING_IDX_MASK(c);
209 len = conringp - c;
210 if ( (idx + len) > conring_size )
211 len = conring_size - idx;
212 if ( (sofar + len) > max )
213 len = max - sofar;
214 if ( copy_to_guest_offset(str, sofar, &conring[idx], len) )
215 return -EFAULT;
216 sofar += len;
217 c += len;
218 }
220 if ( op->clear )
221 {
222 spin_lock_irq(&console_lock);
223 if ( (uint32_t)(conringp - c) > conring_size )
224 conringc = conringp - conring_size;
225 else
226 conringc = c;
227 spin_unlock_irq(&console_lock);
228 }
230 op->count = sofar;
231 op->index = c;
233 return 0;
234 }
237 /*
238 * *******************************************************
239 * *************** ACCESS TO SERIAL LINE *****************
240 * *******************************************************
241 */
243 /* Characters received over the serial line are buffered for domain 0. */
244 #define SERIAL_RX_SIZE 128
245 #define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
246 static char serial_rx_ring[SERIAL_RX_SIZE];
247 static unsigned int serial_rx_cons, serial_rx_prod;
249 static void (*serial_steal_fn)(const char *);
251 int console_steal(int handle, void (*fn)(const char *))
252 {
253 if ( (handle == -1) || (handle != sercon_handle) )
254 return 0;
256 if ( serial_steal_fn != NULL )
257 return -EBUSY;
259 serial_steal_fn = fn;
260 return 1;
261 }
263 void console_giveback(int id)
264 {
265 if ( id == 1 )
266 serial_steal_fn = NULL;
267 }
269 static void sercon_puts(const char *s)
270 {
271 if ( serial_steal_fn != NULL )
272 (*serial_steal_fn)(s);
273 else
274 serial_puts(sercon_handle, s);
275 }
277 /* CTRL-<switch_char> switches input direction between Xen and DOM0. */
278 #define switch_code (opt_conswitch[0]-'a'+1)
279 static int __read_mostly xen_rx = 1; /* FALSE => serial input passed to domain 0. */
281 static void switch_serial_input(void)
282 {
283 static char *input_str[2] = { "DOM0", "Xen" };
284 xen_rx = !xen_rx;
285 printk("*** Serial input -> %s", input_str[xen_rx]);
286 if ( switch_code )
287 printk(" (type 'CTRL-%c' three times to switch input to %s)",
288 opt_conswitch[0], input_str[!xen_rx]);
289 printk("\n");
290 }
292 static void __serial_rx(char c, struct cpu_user_regs *regs)
293 {
294 if ( xen_rx )
295 return handle_keypress(c, regs);
297 /* Deliver input to guest buffer, unless it is already full. */
298 if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
299 serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
300 /* Always notify the guest: prevents receive path from getting stuck. */
301 send_guest_global_virq(dom0, VIRQ_CONSOLE);
302 }
304 static void serial_rx(char c, struct cpu_user_regs *regs)
305 {
306 static int switch_code_count = 0;
308 if ( switch_code && (c == switch_code) )
309 {
310 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
311 if ( ++switch_code_count == 3 )
312 {
313 switch_serial_input();
314 switch_code_count = 0;
315 }
316 return;
317 }
319 for ( ; switch_code_count != 0; switch_code_count-- )
320 __serial_rx(switch_code, regs);
322 /* Finally process the just-received character. */
323 __serial_rx(c, regs);
324 }
326 static void notify_dom0_con_ring(unsigned long unused)
327 {
328 send_guest_global_virq(dom0, VIRQ_CON_RING);
329 }
330 static DECLARE_TASKLET(notify_dom0_con_ring_tasklet, notify_dom0_con_ring, 0);
332 static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
333 {
334 char kbuf[128], *kptr;
335 int kcount;
337 while ( count > 0 )
338 {
339 if ( hypercall_preempt_check() )
340 return hypercall_create_continuation(
341 __HYPERVISOR_console_io, "iih",
342 CONSOLEIO_write, count, buffer);
344 kcount = min_t(int, count, sizeof(kbuf)-1);
345 if ( copy_from_guest(kbuf, buffer, kcount) )
346 return -EFAULT;
347 kbuf[kcount] = '\0';
349 spin_lock_irq(&console_lock);
351 sercon_puts(kbuf);
352 vga_puts(kbuf);
354 if ( opt_console_to_ring )
355 {
356 for ( kptr = kbuf; *kptr != '\0'; kptr++ )
357 putchar_console_ring(*kptr);
358 tasklet_schedule(&notify_dom0_con_ring_tasklet);
359 }
361 spin_unlock_irq(&console_lock);
363 guest_handle_add_offset(buffer, kcount);
364 count -= kcount;
365 }
367 return 0;
368 }
370 long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
371 {
372 long rc;
373 unsigned int idx, len;
375 #ifndef VERBOSE
376 /* Only domain 0 may access the emergency console. */
377 if ( current->domain->domain_id != 0 )
378 return -EPERM;
379 #endif
381 rc = xsm_console_io(current->domain, cmd);
382 if ( rc )
383 return rc;
385 switch ( cmd )
386 {
387 case CONSOLEIO_write:
388 rc = guest_console_write(buffer, count);
389 break;
390 case CONSOLEIO_read:
391 rc = 0;
392 while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
393 {
394 idx = SERIAL_RX_MASK(serial_rx_cons);
395 len = serial_rx_prod - serial_rx_cons;
396 if ( (idx + len) > SERIAL_RX_SIZE )
397 len = SERIAL_RX_SIZE - idx;
398 if ( (rc + len) > count )
399 len = count - rc;
400 if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) )
401 {
402 rc = -EFAULT;
403 break;
404 }
405 rc += len;
406 serial_rx_cons += len;
407 }
408 break;
409 default:
410 rc = -ENOSYS;
411 break;
412 }
414 return rc;
415 }
418 /*
419 * *****************************************************
420 * *************** GENERIC CONSOLE I/O *****************
421 * *****************************************************
422 */
424 static bool_t console_locks_busted;
426 static void __putstr(const char *str)
427 {
428 int c;
430 ASSERT(spin_is_locked(&console_lock));
432 sercon_puts(str);
433 vga_puts(str);
435 if ( !console_locks_busted )
436 {
437 while ( (c = *str++) != '\0' )
438 putchar_console_ring(c);
439 tasklet_schedule(&notify_dom0_con_ring_tasklet);
440 }
441 }
443 static int printk_prefix_check(char *p, char **pp)
444 {
445 int loglvl = -1;
446 int upper_thresh = xenlog_upper_thresh;
447 int lower_thresh = xenlog_lower_thresh;
449 while ( (p[0] == '<') && (p[1] != '\0') && (p[2] == '>') )
450 {
451 switch ( p[1] )
452 {
453 case 'G':
454 upper_thresh = xenlog_guest_upper_thresh;
455 lower_thresh = xenlog_guest_lower_thresh;
456 if ( loglvl == -1 )
457 loglvl = XENLOG_GUEST_DEFAULT;
458 break;
459 case '0' ... '3':
460 loglvl = p[1] - '0';
461 break;
462 }
463 p += 3;
464 }
466 if ( loglvl == -1 )
467 loglvl = XENLOG_DEFAULT;
469 *pp = p;
471 return ((atomic_read(&print_everything) != 0) ||
472 (loglvl < lower_thresh) ||
473 ((loglvl < upper_thresh) && printk_ratelimit()));
474 }
476 static void printk_start_of_line(void)
477 {
478 struct tm tm;
479 char tstr[32];
481 __putstr("(XEN) ");
483 if ( !opt_console_timestamps )
484 return;
486 tm = wallclock_time();
487 if ( tm.tm_mday == 0 )
488 return;
490 snprintf(tstr, sizeof(tstr), "[%04u-%02u-%02u %02u:%02u:%02u] ",
491 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
492 tm.tm_hour, tm.tm_min, tm.tm_sec);
493 __putstr(tstr);
494 }
496 void printk(const char *fmt, ...)
497 {
498 static char buf[1024];
499 static int start_of_line = 1, do_print;
501 va_list args;
502 char *p, *q;
503 unsigned long flags;
505 /* console_lock can be acquired recursively from __printk_ratelimit(). */
506 local_irq_save(flags);
507 spin_lock_recursive(&console_lock);
509 va_start(args, fmt);
510 (void)vsnprintf(buf, sizeof(buf), fmt, args);
511 va_end(args);
513 p = buf;
515 while ( (q = strchr(p, '\n')) != NULL )
516 {
517 *q = '\0';
518 if ( start_of_line )
519 do_print = printk_prefix_check(p, &p);
520 if ( do_print )
521 {
522 if ( start_of_line )
523 printk_start_of_line();
524 __putstr(p);
525 __putstr("\n");
526 }
527 start_of_line = 1;
528 p = q + 1;
529 }
531 if ( *p != '\0' )
532 {
533 if ( start_of_line )
534 do_print = printk_prefix_check(p, &p);
535 if ( do_print )
536 {
537 if ( start_of_line )
538 printk_start_of_line();
539 __putstr(p);
540 }
541 start_of_line = 0;
542 }
544 spin_unlock_recursive(&console_lock);
545 local_irq_restore(flags);
546 }
548 void __init console_init_preirq(void)
549 {
550 char *p;
552 serial_init_preirq();
554 /* Where should console output go? */
555 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
556 {
557 if ( *p == ',' )
558 p++;
559 if ( !strncmp(p, "vga", 3) )
560 vga_init();
561 else if ( strncmp(p, "com", 3) ||
562 (sercon_handle = serial_parse_handle(p)) == -1 )
563 {
564 char *q = strchr(p, ',');
565 if ( q != NULL )
566 *q = '\0';
567 printk("Bad console= option '%s'\n", p);
568 if ( q != NULL )
569 *q = ',';
570 }
571 }
573 serial_set_rx_handler(sercon_handle, serial_rx);
575 /* HELLO WORLD --- start-of-day banner text. */
576 spin_lock(&console_lock);
577 __putstr(xen_banner());
578 spin_unlock(&console_lock);
579 printk("Xen version %d.%d%s (%s@%s) (%s) %s\n",
580 xen_major_version(), xen_minor_version(), xen_extra_version(),
581 xen_compile_by(), xen_compile_domain(),
582 xen_compiler(), xen_compile_date());
583 printk("Latest ChangeSet: %s\n", xen_changeset());
585 if ( opt_sync_console )
586 {
587 serial_start_sync(sercon_handle);
588 add_taint(TAINT_SYNC_CONSOLE);
589 printk("Console output is synchronous.\n");
590 }
591 }
593 void __init console_init_postirq(void)
594 {
595 char *ring;
596 unsigned int i, order;
598 serial_init_postirq();
600 if ( !opt_conring_size )
601 opt_conring_size = num_present_cpus() << (9 + xenlog_lower_thresh);
603 order = get_order_from_bytes(max(opt_conring_size, conring_size));
604 while ( (ring = alloc_xenheap_pages(order, 0)) == NULL )
605 {
606 BUG_ON(order == 0);
607 order--;
608 }
609 opt_conring_size = PAGE_SIZE << order;
611 spin_lock_irq(&console_lock);
612 for ( i = conringc ; i != conringp; i++ )
613 ring[i & (opt_conring_size - 1)] = conring[i & (conring_size - 1)];
614 conring = ring;
615 wmb(); /* Allow users of console_force_unlock() to see larger buffer. */
616 conring_size = opt_conring_size;
617 spin_unlock_irq(&console_lock);
619 printk("Allocated console ring of %u KiB.\n", opt_conring_size >> 10);
620 }
622 void __init console_endboot(void)
623 {
624 int i, j;
626 printk("Std. Loglevel: %s", loglvl_str(xenlog_lower_thresh));
627 if ( xenlog_upper_thresh != xenlog_lower_thresh )
628 printk(" (Rate-limited: %s)", loglvl_str(xenlog_upper_thresh));
629 printk("\nGuest Loglevel: %s", loglvl_str(xenlog_guest_lower_thresh));
630 if ( xenlog_guest_upper_thresh != xenlog_guest_lower_thresh )
631 printk(" (Rate-limited: %s)", loglvl_str(xenlog_guest_upper_thresh));
632 printk("\n");
634 if ( opt_sync_console )
635 {
636 printk("**********************************************\n");
637 printk("******* WARNING: CONSOLE OUTPUT IS SYNCHRONOUS\n");
638 printk("******* This option is intended to aid debugging "
639 "of Xen by ensuring\n");
640 printk("******* that all output is synchronously delivered "
641 "on the serial line.\n");
642 printk("******* However it can introduce SIGNIFICANT latencies "
643 "and affect\n");
644 printk("******* timekeeping. It is NOT recommended for "
645 "production use!\n");
646 printk("**********************************************\n");
647 for ( i = 0; i < 3; i++ )
648 {
649 printk("%d... ", 3-i);
650 for ( j = 0; j < 100; j++ )
651 {
652 process_pending_softirqs();
653 mdelay(10);
654 }
655 }
656 printk("\n");
657 }
659 vga_endboot();
661 /*
662 * If user specifies so, we fool the switch routine to redirect input
663 * straight back to Xen. I use this convoluted method so we still print
664 * a useful 'how to switch' message.
665 */
666 if ( opt_conswitch[1] == 'x' )
667 xen_rx = !xen_rx;
669 /* Serial input is directed to DOM0 by default. */
670 switch_serial_input();
671 }
673 int __init console_has(const char *device)
674 {
675 char *p;
677 for ( p = opt_console; p != NULL; p = strchr(p, ',') )
678 {
679 if ( *p == ',' )
680 p++;
681 if ( strncmp(p, device, strlen(device)) == 0 )
682 return 1;
683 }
685 return 0;
686 }
688 void console_start_log_everything(void)
689 {
690 serial_start_log_everything(sercon_handle);
691 atomic_inc(&print_everything);
692 }
694 void console_end_log_everything(void)
695 {
696 serial_end_log_everything(sercon_handle);
697 atomic_dec(&print_everything);
698 }
700 void console_force_unlock(void)
701 {
702 spin_lock_init(&console_lock);
703 serial_force_unlock(sercon_handle);
704 console_locks_busted = 1;
705 console_start_sync();
706 }
708 void console_start_sync(void)
709 {
710 atomic_inc(&print_everything);
711 serial_start_sync(sercon_handle);
712 }
714 void console_end_sync(void)
715 {
716 serial_end_sync(sercon_handle);
717 atomic_dec(&print_everything);
718 }
720 /*
721 * printk rate limiting, lifted from Linux.
722 *
723 * This enforces a rate limit: not more than one kernel message
724 * every printk_ratelimit_ms (millisecs).
725 */
726 int __printk_ratelimit(int ratelimit_ms, int ratelimit_burst)
727 {
728 static DEFINE_SPINLOCK(ratelimit_lock);
729 static unsigned long toks = 10 * 5 * 1000;
730 static unsigned long last_msg;
731 static int missed;
732 unsigned long flags;
733 unsigned long long now = NOW(); /* ns */
734 unsigned long ms;
736 do_div(now, 1000000);
737 ms = (unsigned long)now;
739 spin_lock_irqsave(&ratelimit_lock, flags);
740 toks += ms - last_msg;
741 last_msg = ms;
742 if ( toks > (ratelimit_burst * ratelimit_ms))
743 toks = ratelimit_burst * ratelimit_ms;
744 if ( toks >= ratelimit_ms )
745 {
746 int lost = missed;
747 missed = 0;
748 toks -= ratelimit_ms;
749 spin_unlock(&ratelimit_lock);
750 if ( lost )
751 {
752 char lost_str[8];
753 snprintf(lost_str, sizeof(lost_str), "%d", lost);
754 /* console_lock may already be acquired by printk(). */
755 spin_lock_recursive(&console_lock);
756 printk_start_of_line();
757 __putstr("printk: ");
758 __putstr(lost_str);
759 __putstr(" messages suppressed.\n");
760 spin_unlock_recursive(&console_lock);
761 }
762 local_irq_restore(flags);
763 return 1;
764 }
765 missed++;
766 spin_unlock_irqrestore(&ratelimit_lock, flags);
767 return 0;
768 }
770 /* minimum time in ms between messages */
771 static int __read_mostly printk_ratelimit_ms = 5 * 1000;
773 /* number of messages we send before ratelimiting */
774 static int __read_mostly printk_ratelimit_burst = 10;
776 int printk_ratelimit(void)
777 {
778 return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst);
779 }
781 /*
782 * **************************************************************
783 * *************** Serial console ring buffer *******************
784 * **************************************************************
785 */
787 #ifdef DEBUG_TRACE_DUMP
789 /* Send output direct to console, or buffer it? */
790 static volatile int debugtrace_send_to_console;
792 static char *debugtrace_buf; /* Debug-trace buffer */
793 static unsigned int debugtrace_prd; /* Producer index */
794 static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;
795 static unsigned int debugtrace_used;
796 static DEFINE_SPINLOCK(debugtrace_lock);
797 integer_param("debugtrace", debugtrace_kilobytes);
799 static void debugtrace_dump_worker(void)
800 {
801 if ( (debugtrace_bytes == 0) || !debugtrace_used )
802 return;
804 printk("debugtrace_dump() starting\n");
806 /* Print oldest portion of the ring. */
807 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
808 sercon_puts(&debugtrace_buf[debugtrace_prd]);
810 /* Print youngest portion of the ring. */
811 debugtrace_buf[debugtrace_prd] = '\0';
812 sercon_puts(&debugtrace_buf[0]);
814 memset(debugtrace_buf, '\0', debugtrace_bytes);
816 printk("debugtrace_dump() finished\n");
817 }
819 static void debugtrace_toggle(void)
820 {
821 unsigned long flags;
823 watchdog_disable();
824 spin_lock_irqsave(&debugtrace_lock, flags);
826 /*
827 * Dump the buffer *before* toggling, in case the act of dumping the
828 * buffer itself causes more printk() invocations.
829 */
830 printk("debugtrace_printk now writing to %s.\n",
831 !debugtrace_send_to_console ? "console": "buffer");
832 if ( !debugtrace_send_to_console )
833 debugtrace_dump_worker();
835 debugtrace_send_to_console = !debugtrace_send_to_console;
837 spin_unlock_irqrestore(&debugtrace_lock, flags);
838 watchdog_enable();
840 }
842 void debugtrace_dump(void)
843 {
844 unsigned long flags;
846 watchdog_disable();
847 spin_lock_irqsave(&debugtrace_lock, flags);
849 debugtrace_dump_worker();
851 spin_unlock_irqrestore(&debugtrace_lock, flags);
852 watchdog_enable();
853 }
855 void debugtrace_printk(const char *fmt, ...)
856 {
857 static char buf[1024];
858 static u32 count;
860 va_list args;
861 char *p;
862 unsigned long flags;
864 if ( debugtrace_bytes == 0 )
865 return;
867 debugtrace_used = 1;
869 spin_lock_irqsave(&debugtrace_lock, flags);
871 ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
873 snprintf(buf, sizeof(buf), "%u ", ++count);
875 va_start(args, fmt);
876 (void)vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt, args);
877 va_end(args);
879 if ( debugtrace_send_to_console )
880 {
881 serial_puts(sercon_handle, buf);
882 }
883 else
884 {
885 for ( p = buf; *p != '\0'; p++ )
886 {
887 debugtrace_buf[debugtrace_prd++] = *p;
888 /* Always leave a nul byte at the end of the buffer. */
889 if ( debugtrace_prd == (debugtrace_bytes - 1) )
890 debugtrace_prd = 0;
891 }
892 }
894 spin_unlock_irqrestore(&debugtrace_lock, flags);
895 }
897 static void debugtrace_key(unsigned char key)
898 {
899 debugtrace_toggle();
900 }
902 static struct keyhandler debugtrace_keyhandler = {
903 .u.fn = debugtrace_key,
904 .desc = "toggle debugtrace to console/buffer"
905 };
907 static int __init debugtrace_init(void)
908 {
909 int order;
910 unsigned int kbytes, bytes;
912 /* Round size down to next power of two. */
913 while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 )
914 debugtrace_kilobytes = kbytes;
916 bytes = debugtrace_kilobytes << 10;
917 if ( bytes == 0 )
918 return 0;
920 order = get_order_from_bytes(bytes);
921 debugtrace_buf = alloc_xenheap_pages(order, 0);
922 ASSERT(debugtrace_buf != NULL);
924 memset(debugtrace_buf, '\0', bytes);
926 debugtrace_bytes = bytes;
928 register_keyhandler('T', &debugtrace_keyhandler);
930 return 0;
931 }
932 __initcall(debugtrace_init);
934 #endif /* !NDEBUG */
937 /*
938 * **************************************************************
939 * *************** Debugging/tracing/error-report ***************
940 * **************************************************************
941 */
943 void panic(const char *fmt, ...)
944 {
945 va_list args;
946 unsigned long flags;
947 static DEFINE_SPINLOCK(lock);
948 static char buf[128];
950 debugtrace_dump();
952 /* Protects buf[] and ensure multi-line message prints atomically. */
953 spin_lock_irqsave(&lock, flags);
955 va_start(args, fmt);
956 (void)vsnprintf(buf, sizeof(buf), fmt, args);
957 va_end(args);
959 console_start_sync();
960 printk("\n****************************************\n");
961 printk("Panic on CPU %d:\n", smp_processor_id());
962 printk("%s", buf);
963 printk("****************************************\n\n");
964 if ( opt_noreboot )
965 printk("Manual reset required ('noreboot' specified)\n");
966 else
967 printk("Reboot in five seconds...\n");
969 spin_unlock_irqrestore(&lock, flags);
971 debugger_trap_immediate();
973 kexec_crash();
975 if ( opt_noreboot )
976 {
977 machine_halt();
978 }
979 else
980 {
981 watchdog_disable();
982 machine_restart(5000);
983 }
984 }
986 void __bug(char *file, int line)
987 {
988 console_start_sync();
989 printk("Xen BUG at %s:%d\n", file, line);
990 dump_execution_state();
991 panic("Xen BUG at %s:%d\n", file, line);
992 for ( ; ; ) ;
993 }
995 void __warn(char *file, int line)
996 {
997 printk("Xen WARN at %s:%d\n", file, line);
998 dump_execution_state();
999 }
1002 /*
1003 * **************************************************************
1004 * ****************** Console suspend/resume ********************
1005 * **************************************************************
1006 */
1008 static void suspend_steal_fn(const char *str) { }
1009 static int suspend_steal_id;
1011 int console_suspend(void)
1013 suspend_steal_id = console_steal(sercon_handle, suspend_steal_fn);
1014 serial_suspend();
1015 return 0;
1018 int console_resume(void)
1020 serial_resume();
1021 console_giveback(suspend_steal_id);
1022 return 0;
1025 /*
1026 * Local variables:
1027 * mode: C
1028 * c-set-style: "BSD"
1029 * c-basic-offset: 4
1030 * tab-width: 4
1031 * indent-tabs-mode: nil
1032 * End:
1033 */