commit 8f1c423046c22dad6aaeca04bfcb0ab301843c36
Author: Maxim Levitsky <maximlevitsky@gmail.com>
Date: Sat Jul 31 13:43:03 2010 +0300
printk: Allow to fix the physical address of printk buffer
Allows to put printk buffer at fixed location of ram (default 128M).
If debugfs is enabled, log of last boot is copied into
system ram, and can be accessed via debugfs, for example
cat /sys/kernel/debug/printk/crash_dmesg
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
@@ -46,6 +46,7 @@ extern unsigned long saved_video_mode;
extern void reserve_standard_io_resources(void);
extern void i386_reserve_resources(void);
extern void setup_default_timer_irq(void);
+extern void early_reserve_printk_buffer(void);
#ifdef CONFIG_X86_MRST
extern void x86_mrst_early_setup(void);
@@ -843,6 +843,7 @@ void __init setup_arch(char **cmdline_p)
/* after early param, so could get panic from serial */
reserve_early_setup_data();
+ early_reserve_printk_buffer();
if (acpi_mps_check()) {
#ifdef CONFIG_X86_LOCAL_APIC
@@ -106,7 +106,6 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
return NULL;
- WARN_ON_ONCE(is_ram);
}
/*
@@ -41,6 +41,7 @@
#include <linux/notifier.h>
#include <asm/uaccess.h>
+#include <linux/debugfs.h>
/*
* for_each_console() allows you to iterate on each console
@@ -167,6 +168,7 @@ void log_buf_kexec_setup(void)
}
#endif
+#ifndef CONFIG_HWMEM_PRINTK
static int __init log_buf_len_setup(char *str)
{
unsigned size = memparse(str, &str);
@@ -207,6 +209,93 @@ out:
}
__setup("log_buf_len=", log_buf_len_setup);
+#endif
+
+#ifdef CONFIG_HWMEM_PRINTK
+
+char *old_log_buf;
+struct debugfs_blob_wrapper crash_dmesg_wrapper;
+static unsigned int printk_phys_address = CONFIG_HWMEM_PRINTK_DEFAULT_ADDRESS;
+
+
+static int __init printk_address_setup(char *p)
+{
+ char *tmp;
+
+ if (!strncmp(p, "off", 3))
+ printk_phys_address = 0;
+ else
+ printk_phys_address = memparse(p, &tmp);
+ return 0;
+}
+early_param("printk_address", printk_address_setup);
+
+
+void early_reserve_printk_buffer(void)
+{
+ if (printk_phys_address)
+ reserve_early(printk_phys_address,
+ printk_phys_address + __LOG_BUF_LEN, "printk buffer");
+}
+
+static int printk_move_to_fixed_address(void)
+{
+
+ char *mem_address;
+ unsigned long flags;
+ struct dentry *dbgfs_dir;
+
+ if (!printk_phys_address)
+ return 0;
+
+ mem_address = ioremap(printk_phys_address, __LOG_BUF_LEN);
+
+ if (!mem_address) {
+ printk(KERN_ALERT "Can't map hardware kernel log memory."
+ "printk buffer disabled\n");
+ return 0;
+ }
+
+ printk(KERN_INFO "Logging kernel messages into HW memory at 0x%08x\n",
+ printk_phys_address);
+
+ /* allocate saved log buffer, and save the log memory that we
+ will otherwise overwrite */
+ old_log_buf = kmalloc(__LOG_BUF_LEN, GFP_KERNEL);
+ if (old_log_buf)
+ memcpy(old_log_buf, mem_address, __LOG_BUF_LEN);
+
+
+ /* copy current log to the new memory */
+ memcpy(mem_address, log_buf, __LOG_BUF_LEN);
+
+ /* save the log memory, and publish it */
+ if (old_log_buf) {
+
+ crash_dmesg_wrapper.data = old_log_buf;
+ crash_dmesg_wrapper.size = __LOG_BUF_LEN;
+
+ dbgfs_dir = debugfs_create_dir("printk", NULL);
+
+ if (dbgfs_dir > 0)
+ debugfs_create_blob("crash_dmesg", S_IRUSR, dbgfs_dir,
+ &crash_dmesg_wrapper);
+ }
+
+
+
+ /* switch to the full log memory now */
+ spin_lock_irqsave(&logbuf_lock, flags);
+ log_buf = mem_address;
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ return 1;
+}
+postcore_initcall(printk_move_to_fixed_address);
+
+#else
+void early_reserve_printk_buffer(void) {}
+#endif
#ifdef CONFIG_BOOT_PRINTK_DELAY
@@ -788,6 +788,35 @@ config BOOT_PRINTK_DELAY
BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect
what it believes to be lockup conditions.
+config HWMEM_PRINTK
+ bool "Log printk message buffer into fixed physical address (DANGEROUS)"
+ depends on DEBUG_KERNEL && PRINTK
+ help
+ This option allows to place kernel log buffer into pre-defined
+ area, somewhere in memory space.
+
+ This creates some sort of black box recorder and can be very useful
+ to debug several problems, especially 'panics' that happen while you
+ use the X window system.
+
+
+ If you also select debugfs support, you can easily look at
+ kernel log of failed boot at:
+ /sys/kernel/debug/printk/crash_dmesg
+
+ (Assuming you mounted debugfs on /sys/kernel/debug)
+
+ Misuse of this option can be DANGEROUS, as it makes kernel write at
+ arbitary (selected by you) hardware memory range.
+
+ It is only intended for debbuging, so say 'no' if not sure
+
+config HWMEM_PRINTK_DEFAULT_ADDRESS
+ hex
+ depends on HWMEM_PRINTK
+ prompt "Default address at which store the printk buffer (default 60M)"
+ default "0x3C00000"
+
config RCU_TORTURE_TEST
tristate "torture tests for RCU"
depends on DEBUG_KERNEL