|  | /* | 
|  | * Copyright 2010 Tilera Corporation. All Rights Reserved. | 
|  | * | 
|  | *   This program is free software; you can redistribute it and/or | 
|  | *   modify it under the terms of the GNU General Public License | 
|  | *   as published by the Free Software Foundation, version 2. | 
|  | * | 
|  | *   This program is distributed in the hope that it will be useful, but | 
|  | *   WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 
|  | *   NON INFRINGEMENT.  See the GNU General Public License for | 
|  | *   more details. | 
|  | */ | 
|  |  | 
|  | #include <linux/console.h> | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/init.h> | 
|  | #include <linux/string.h> | 
|  | #include <linux/irqflags.h> | 
|  | #include <asm/setup.h> | 
|  | #include <hv/hypervisor.h> | 
|  |  | 
|  | static void early_hv_write(struct console *con, const char *s, unsigned n) | 
|  | { | 
|  | hv_console_write((HV_VirtAddr) s, n); | 
|  | } | 
|  |  | 
|  | static struct console early_hv_console = { | 
|  | .name =		"earlyhv", | 
|  | .write =	early_hv_write, | 
|  | .flags =	CON_PRINTBUFFER, | 
|  | .index =	-1, | 
|  | }; | 
|  |  | 
|  | /* Direct interface for emergencies */ | 
|  | static struct console *early_console = &early_hv_console; | 
|  | static int early_console_initialized; | 
|  | static int early_console_complete; | 
|  |  | 
|  | static void early_vprintk(const char *fmt, va_list ap) | 
|  | { | 
|  | char buf[512]; | 
|  | int n = vscnprintf(buf, sizeof(buf), fmt, ap); | 
|  | early_console->write(early_console, buf, n); | 
|  | } | 
|  |  | 
|  | void early_printk(const char *fmt, ...) | 
|  | { | 
|  | va_list ap; | 
|  | va_start(ap, fmt); | 
|  | early_vprintk(fmt, ap); | 
|  | va_end(ap); | 
|  | } | 
|  |  | 
|  | void early_panic(const char *fmt, ...) | 
|  | { | 
|  | va_list ap; | 
|  | arch_local_irq_disable_all(); | 
|  | va_start(ap, fmt); | 
|  | early_printk("Kernel panic - not syncing: "); | 
|  | early_vprintk(fmt, ap); | 
|  | early_console->write(early_console, "\n", 1); | 
|  | va_end(ap); | 
|  | dump_stack(); | 
|  | hv_halt(); | 
|  | } | 
|  |  | 
|  | static int __initdata keep_early; | 
|  |  | 
|  | static int __init setup_early_printk(char *str) | 
|  | { | 
|  | if (early_console_initialized) | 
|  | return 1; | 
|  |  | 
|  | if (str != NULL && strncmp(str, "keep", 4) == 0) | 
|  | keep_early = 1; | 
|  |  | 
|  | early_console = &early_hv_console; | 
|  | early_console_initialized = 1; | 
|  | register_console(early_console); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void __init disable_early_printk(void) | 
|  | { | 
|  | early_console_complete = 1; | 
|  | if (!early_console_initialized || !early_console) | 
|  | return; | 
|  | if (!keep_early) { | 
|  | early_printk("disabling early console\n"); | 
|  | unregister_console(early_console); | 
|  | early_console_initialized = 0; | 
|  | } else { | 
|  | early_printk("keeping early console\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void warn_early_printk(void) | 
|  | { | 
|  | if (early_console_complete || early_console_initialized) | 
|  | return; | 
|  | early_printk("\ | 
|  | Machine shutting down before console output is fully initialized.\n\ | 
|  | You may wish to reboot and add the option 'earlyprintk' to your\n\ | 
|  | boot command line to see any diagnostic early console output.\n\ | 
|  | "); | 
|  | } | 
|  |  | 
|  | early_param("earlyprintk", setup_early_printk); |