📄 console.c
字号:
(void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); p = buf; while ( (q = strchr(p, '\n')) != NULL ) { *q = '\0'; if ( start_of_line ) do_print = printk_prefix_check(p, &p); if ( do_print ) { if ( start_of_line ) printk_start_of_line(); __putstr(p); __putstr("\n"); } start_of_line = 1; p = q + 1; } if ( *p != '\0' ) { if ( start_of_line ) do_print = printk_prefix_check(p, &p); if ( do_print ) { if ( start_of_line ) printk_start_of_line(); __putstr(p); } start_of_line = 0; } spin_unlock_recursive(&console_lock); local_irq_restore(flags);}void __init init_console(void){ char *p; /* Where should console output go? */ for ( p = opt_console; p != NULL; p = strchr(p, ',') ) { if ( *p == ',' ) p++; if ( strncmp(p, "com", 3) == 0 ) sercon_handle = serial_parse_handle(p); else if ( strncmp(p, "vga", 3) == 0 ) vga_init(); } serial_set_rx_handler(sercon_handle, serial_rx); /* HELLO WORLD --- start-of-day banner text. */ spin_lock(&console_lock); __putstr(xen_banner()); spin_unlock(&console_lock); printk("Xen version %d.%d%s (%s@%s) (%s) %s\n", xen_major_version(), xen_minor_version(), xen_extra_version(), xen_compile_by(), xen_compile_domain(), xen_compiler(), xen_compile_date()); printk("Latest ChangeSet: %s\n", xen_changeset()); if ( opt_sync_console ) { serial_start_sync(sercon_handle); add_taint(TAINT_SYNC_CONSOLE); printk("Console output is synchronous.\n"); }}void __init console_endboot(void){ int i, j; printk("Std. Loglevel: %s", loglvl_str(xenlog_lower_thresh)); if ( xenlog_upper_thresh != xenlog_lower_thresh ) printk(" (Rate-limited: %s)", loglvl_str(xenlog_upper_thresh)); printk("\nGuest Loglevel: %s", loglvl_str(xenlog_guest_lower_thresh)); if ( xenlog_guest_upper_thresh != xenlog_guest_lower_thresh ) printk(" (Rate-limited: %s)", loglvl_str(xenlog_guest_upper_thresh)); printk("\n"); if ( opt_sync_console ) { printk("**********************************************\n"); printk("******* WARNING: CONSOLE OUTPUT IS SYNCHRONOUS\n"); printk("******* This option is intended to aid debugging " "of Xen by ensuring\n"); printk("******* that all output is synchronously delivered " "on the serial line.\n"); printk("******* However it can introduce SIGNIFICANT latencies " "and affect\n"); printk("******* timekeeping. It is NOT recommended for " "production use!\n"); printk("**********************************************\n"); for ( i = 0; i < 3; i++ ) { printk("%d... ", 3-i); for ( j = 0; j < 100; j++ ) { process_pending_timers(); mdelay(10); } } printk("\n"); } vga_endboot(); /* * If user specifies so, we fool the switch routine to redirect input * straight back to Xen. I use this convoluted method so we still print * a useful 'how to switch' message. */ if ( opt_conswitch[1] == 'x' ) xen_rx = !xen_rx; /* Serial input is directed to DOM0 by default. */ switch_serial_input();}int console_has(const char *device){ char *p; for ( p = opt_console; p != NULL; p = strchr(p, ',') ) { if ( *p == ',' ) p++; if ( strncmp(p, device, strlen(device)) == 0 ) return 1; } return 0;}void console_start_log_everything(void){ serial_start_log_everything(sercon_handle); atomic_inc(&print_everything);}void console_end_log_everything(void){ serial_end_log_everything(sercon_handle); atomic_dec(&print_everything);}void console_force_unlock(void){ spin_lock_init(&console_lock); serial_force_unlock(sercon_handle); console_start_sync();}void console_force_lock(void){ spin_lock(&console_lock);}void console_start_sync(void){ atomic_inc(&print_everything); serial_start_sync(sercon_handle);}void console_end_sync(void){ serial_end_sync(sercon_handle); atomic_dec(&print_everything);}void console_putc(char c){ serial_putc(sercon_handle, c);}int console_getc(void){ return serial_getc(sercon_handle);}/* * printk rate limiting, lifted from Linux. * * This enforces a rate limit: not more than one kernel message * every printk_ratelimit_ms (millisecs). */int __printk_ratelimit(int ratelimit_ms, int ratelimit_burst){ static DEFINE_SPINLOCK(ratelimit_lock); static unsigned long toks = 10 * 5 * 1000; static unsigned long last_msg; static int missed; unsigned long flags; unsigned long long now = NOW(); /* ns */ unsigned long ms; do_div(now, 1000000); ms = (unsigned long)now; spin_lock_irqsave(&ratelimit_lock, flags); toks += ms - last_msg; last_msg = ms; if ( toks > (ratelimit_burst * ratelimit_ms)) toks = ratelimit_burst * ratelimit_ms; if ( toks >= ratelimit_ms ) { int lost = missed; missed = 0; toks -= ratelimit_ms; spin_unlock(&ratelimit_lock); if ( lost ) { char lost_str[8]; snprintf(lost_str, sizeof(lost_str), "%d", lost); /* console_lock may already be acquired by printk(). */ spin_lock_recursive(&console_lock); printk_start_of_line(); __putstr("printk: "); __putstr(lost_str); __putstr(" messages suppressed.\n"); spin_unlock_recursive(&console_lock); } local_irq_restore(flags); return 1; } missed++; spin_unlock_irqrestore(&ratelimit_lock, flags); return 0;}/* minimum time in ms between messages */int printk_ratelimit_ms = 5 * 1000;/* number of messages we send before ratelimiting */int printk_ratelimit_burst = 10;int printk_ratelimit(void){ return __printk_ratelimit(printk_ratelimit_ms, printk_ratelimit_burst);}/* * ************************************************************** * *************** Serial console ring buffer ******************* * ************************************************************** */#ifdef DEBUG_TRACE_DUMP/* Send output direct to console, or buffer it? */static volatile int debugtrace_send_to_console;static char *debugtrace_buf; /* Debug-trace buffer */static unsigned int debugtrace_prd; /* Producer index */static unsigned int debugtrace_kilobytes = 128, debugtrace_bytes;static unsigned int debugtrace_used;static DEFINE_SPINLOCK(debugtrace_lock);integer_param("debugtrace", debugtrace_kilobytes);static void debugtrace_dump_worker(void){ if ( (debugtrace_bytes == 0) || !debugtrace_used ) return; printk("debugtrace_dump() starting\n"); /* Print oldest portion of the ring. */ ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0); sercon_puts(&debugtrace_buf[debugtrace_prd]); /* Print youngest portion of the ring. */ debugtrace_buf[debugtrace_prd] = '\0'; sercon_puts(&debugtrace_buf[0]); memset(debugtrace_buf, '\0', debugtrace_bytes); printk("debugtrace_dump() finished\n");}static void debugtrace_toggle(void){ unsigned long flags; watchdog_disable(); spin_lock_irqsave(&debugtrace_lock, flags); /* * Dump the buffer *before* toggling, in case the act of dumping the * buffer itself causes more printk() invocations. */ printk("debugtrace_printk now writing to %s.\n", !debugtrace_send_to_console ? "console": "buffer"); if ( !debugtrace_send_to_console ) debugtrace_dump_worker(); debugtrace_send_to_console = !debugtrace_send_to_console; spin_unlock_irqrestore(&debugtrace_lock, flags); watchdog_enable();}void debugtrace_dump(void){ unsigned long flags; watchdog_disable(); spin_lock_irqsave(&debugtrace_lock, flags); debugtrace_dump_worker(); spin_unlock_irqrestore(&debugtrace_lock, flags); watchdog_enable();}void debugtrace_printk(const char *fmt, ...){ static char buf[1024]; static u32 count; va_list args; char *p; unsigned long flags; if ( debugtrace_bytes == 0 ) return; debugtrace_used = 1; spin_lock_irqsave(&debugtrace_lock, flags); ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0); snprintf(buf, sizeof(buf), "%u ", ++count); va_start(args, fmt); (void)vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt, args); va_end(args); if ( debugtrace_send_to_console ) { serial_puts(sercon_handle, buf); } else { for ( p = buf; *p != '\0'; p++ ) { debugtrace_buf[debugtrace_prd++] = *p; /* Always leave a nul byte at the end of the buffer. */ if ( debugtrace_prd == (debugtrace_bytes - 1) ) debugtrace_prd = 0; } } spin_unlock_irqrestore(&debugtrace_lock, flags);}static void debugtrace_key(unsigned char key){ debugtrace_toggle();}static int __init debugtrace_init(void){ int order; unsigned int kbytes, bytes; /* Round size down to next power of two. */ while ( (kbytes = (debugtrace_kilobytes & (debugtrace_kilobytes-1))) != 0 ) debugtrace_kilobytes = kbytes; bytes = debugtrace_kilobytes << 10; if ( bytes == 0 ) return 0; order = get_order_from_bytes(bytes); debugtrace_buf = alloc_xenheap_pages(order); ASSERT(debugtrace_buf != NULL); memset(debugtrace_buf, '\0', bytes); debugtrace_bytes = bytes; register_keyhandler( 'T', debugtrace_key, "toggle debugtrace to console/buffer"); return 0;}__initcall(debugtrace_init);#endif /* !NDEBUG *//* * ************************************************************** * *************** Debugging/tracing/error-report *************** * ************************************************************** */void panic(const char *fmt, ...){ va_list args; unsigned long flags; static DEFINE_SPINLOCK(lock); static char buf[128]; debugtrace_dump(); /* Protects buf[] and ensure multi-line message prints atomically. */ spin_lock_irqsave(&lock, flags); va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); console_start_sync(); printk("\n****************************************\n"); printk("Panic on CPU %d:\n", smp_processor_id()); printk(buf); printk("****************************************\n\n"); if ( opt_noreboot ) printk("Manual reset required ('noreboot' specified)\n"); else printk("Reboot in five seconds...\n"); spin_unlock_irqrestore(&lock, flags); debugger_trap_immediate(); kexec_crash(); if ( opt_noreboot ) { machine_halt(); } else { watchdog_disable(); machine_restart(5000); }}void __bug(char *file, int line){ console_start_sync(); printk("Xen BUG at %s:%d\n", file, line); dump_execution_state(); panic("Xen BUG at %s:%d\n", file, line); for ( ; ; ) ;}void __warn(char *file, int line){ printk("Xen WARN at %s:%d\n", file, line); dump_execution_state();}/* * ************************************************************** * ****************** Console suspend/resume ******************** * ************************************************************** */static void suspend_steal_fn(const char *str) { }static int suspend_steal_id;int console_suspend(void){ suspend_steal_id = console_steal(sercon_handle, suspend_steal_fn); serial_suspend(); return 0;}int console_resume(void){ serial_resume(); console_giveback(suspend_steal_id); return 0;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -