From 760a674ae7e54f2b867ff6ab0602feb9774d396d Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Tue, 15 Jan 2013 09:40:36 +0800 Subject: [PATCH] rk: last_log: fix printk over read bug 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 | 12 +++++++----- kernel/printk.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/plat-rk/last_log.c b/arch/arm/plat-rk/last_log.c index 61a1d83bb2f7..f7efef27877f 100644 --- a/arch/arm/plat-rk/last_log.c +++ b/arch/arm/plat-rk/last_log.c @@ -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); diff --git a/kernel/printk.c b/kernel/printk.c index d99f1fca19a6..aa0f9f7850b2 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -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; -- 2.34.1