rk: last_log: fix printk over read bug
author黄涛 <huangtao@rock-chips.com>
Tue, 15 Jan 2013 01:40:36 +0000 (09:40 +0800)
committer黄涛 <huangtao@rock-chips.com>
Tue, 15 Jan 2013 01:43:06 +0000 (09:43 +0800)
version 2.1, fix this bug:
Unable to handle kernel paging request at virtual address f7180000
pgd = c0404000
[f7180000] *pgd=9002c811, *pte=00000000, *ppte=00000000
Internal error: Oops: 7 [#1] PREEMPT SMP
CPU: 0    Tainted: G         C   (3.0.36+ #265)
PC is at log_prefix+0x2c/0xe0
LR is at console_unlock+0x128/0x1b0

arch/arm/plat-rk/last_log.c
kernel/printk.c

index 61a1d83bb2f79c9ca04e192d7c88d764ca875ea6..f7efef27877f31d714877fefbb50d727fb2a72fb 100644 (file)
@@ -21,7 +21,7 @@
 #define LOG_BUF_LEN    (1 << CONFIG_LOG_BUF_SHIFT)
 #define LOG_BUF_PAGE_ORDER     (CONFIG_LOG_BUF_SHIFT - PAGE_SHIFT)
 static char last_log_buf[LOG_BUF_LEN];
-extern void switch_log_buf(char *new_log_buf, unsigned size);
+extern void __init switch_log_buf(char *new_log_buf, unsigned size);
 
 char *last_log_get(unsigned *size)
 {
@@ -53,14 +53,15 @@ static const struct file_operations last_log_file_ops = {
 
 static void * __init last_log_vmap(phys_addr_t start, unsigned int page_count)
 {
-       struct page *pages[page_count];
+       struct page *pages[page_count + 1];
        unsigned int i;
 
        for (i = 0; i < page_count; i++) {
                phys_addr_t addr = start + i * PAGE_SIZE;
                pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
        }
-       return vmap(pages, page_count, VM_MAP, pgprot_noncached(PAGE_KERNEL));
+       pages[page_count] = pfn_to_page(start >> PAGE_SHIFT);
+       return vmap(pages, page_count + 1, VM_MAP, pgprot_noncached(PAGE_KERNEL));
 }
 
 static int __init last_log_init(void)
@@ -80,9 +81,10 @@ static int __init last_log_init(void)
                return 0;
        }
 
-       pr_info("0x%p map to 0x%p and copy to 0x%p (version 2.0)\n", log_buf, new_log_buf, last_log_buf);
+       pr_info("0x%p map to 0x%p and copy to 0x%p (version 2.1)\n", log_buf, new_log_buf, last_log_buf);
 
-       memcpy(last_log_buf, log_buf, LOG_BUF_LEN);
+       memcpy(last_log_buf, new_log_buf, LOG_BUF_LEN);
+       memset(new_log_buf, 0, LOG_BUF_LEN);
        switch_log_buf(new_log_buf, LOG_BUF_LEN);
 
        entry = create_proc_entry("last_log", S_IFREG | S_IRUGO, NULL);
index d99f1fca19a68c122a389921a48f982577848681..aa0f9f7850b27840ebbe67cd38eb6f932047f8e9 100644 (file)
@@ -1031,7 +1031,7 @@ void pm_emit_log_char(char c)
 #endif
 
 #ifdef CONFIG_RK29_LAST_LOG
-void switch_log_buf(char *new_log_buf, int size)
+void __init switch_log_buf(char *new_log_buf, int size)
 {
        unsigned long flags;