From 011d81c56d6eabbef990fd0bdd7c18122c32424c Mon Sep 17 00:00:00 2001 From: Stricted Date: Mon, 20 Apr 2020 13:09:23 +0000 Subject: [PATCH] implement samsung last_kmsg --- drivers/staging/samsung/Kconfig | 13 +-- drivers/staging/samsung/Makefile | 2 + drivers/staging/samsung/sec_debug_last_kmsg.c | 104 ++++++++++++++++++ include/linux/sec_debug.h | 23 ++++ lib/debug-snapshot.c | 16 ++- 5 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 drivers/staging/samsung/sec_debug_last_kmsg.c create mode 100644 include/linux/sec_debug.h diff --git a/drivers/staging/samsung/Kconfig b/drivers/staging/samsung/Kconfig index c050fdfe10bb..f256c252ddb3 100644 --- a/drivers/staging/samsung/Kconfig +++ b/drivers/staging/samsung/Kconfig @@ -44,6 +44,12 @@ menuconfig SEC_DEBUG Samsung TN Ramdump Feature. Use INFORM3 and magic number at 0xc0000000. if SEC_DEBUG +config SEC_DEBUG_LAST_KMSG + default n + bool "Enable /proc/last_kmsg support" if EMBEDDED + help + This option enables /proc/last_kmsg support. + config SEC_DEBUG_FUPLOAD_DUMP_MORE bool "Dump more information at forced upload" default n @@ -210,13 +216,6 @@ config SEC_LOG_NONCACHED to concern cache flush status for analyzing sudden lockup issue. -config SEC_LOG_LAST_KMSG - default n - bool "Enable /proc/last_kmsg support" if EMBEDDED - depends on SEC_LOG - help - This option enables /proc/last_kmsg support. - config SEC_AVC_LOG default n bool "Enable avc audit log support" if EMBEDDED diff --git a/drivers/staging/samsung/Makefile b/drivers/staging/samsung/Makefile index a6bd573d311f..b50cb3f2d2ee 100644 --- a/drivers/staging/samsung/Makefile +++ b/drivers/staging/samsung/Makefile @@ -21,3 +21,5 @@ obj-$(CONFIG_SEC_REBOOT) += sec_reboot.o obj-$(CONFIG_SEC_MISC) += sec_misc.o # Samsung sec sysfs Feature obj-$(CONFIG_SEC_SYSFS) += sec_sysfs.o + +obj-$(CONFIG_SEC_DEBUG_LAST_KMSG) += sec_debug_last_kmsg.o diff --git a/drivers/staging/samsung/sec_debug_last_kmsg.c b/drivers/staging/samsung/sec_debug_last_kmsg.c new file mode 100644 index 000000000000..37247d5e51e5 --- /dev/null +++ b/drivers/staging/samsung/sec_debug_last_kmsg.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung TN debugging code + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +static char *last_kmsg_buffer; +static size_t last_kmsg_size; + +void sec_debug_save_last_kmsg(unsigned char *head_ptr, unsigned char *curr_ptr, size_t buf_size) +{ + size_t size; + unsigned char *magickey_addr; + + if (!head_ptr || !curr_ptr || head_ptr == curr_ptr) { + pr_err("%s: no data\n", __func__); + return; + } + + if ((curr_ptr - head_ptr) <= 0) { + pr_err("%s: invalid args\n", __func__); + return; + } + size = (size_t)(curr_ptr - head_ptr); + + magickey_addr = head_ptr + buf_size - (size_t)0x08; + + /* provide previous log as last_kmsg */ + if (*((unsigned long long *)magickey_addr) == SEC_LKMSG_MAGICKEY) { + pr_info("%s: sec_log buffer is full\n", __func__); + last_kmsg_size = (size_t)SZ_2M; + last_kmsg_buffer = kzalloc(last_kmsg_size, GFP_NOWAIT); + if (last_kmsg_size && last_kmsg_buffer) { + memcpy(last_kmsg_buffer, curr_ptr, last_kmsg_size - size); + memcpy(last_kmsg_buffer + (last_kmsg_size - size), head_ptr, size); + pr_info("%s: succeeded\n", __func__); + } else { + pr_err("%s: failed\n", __func__); + } + } else { + pr_info("%s: sec_log buffer is not full\n", __func__); + last_kmsg_size = size; + last_kmsg_buffer = kzalloc(last_kmsg_size, GFP_NOWAIT); + if (last_kmsg_size && last_kmsg_buffer) { + memcpy(last_kmsg_buffer, head_ptr, last_kmsg_size); + pr_info("%s: succeeded\n", __func__); + } else { + pr_err("%s: failed\n", __func__); + } + } +} + +static ssize_t sec_last_kmsg_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + loff_t pos = *offset; + ssize_t count; + + if (pos >= last_kmsg_size) + return 0; + + count = min(len, (size_t)(last_kmsg_size - pos)); + if (copy_to_user(buf, last_kmsg_buffer + pos, count)) + return -EFAULT; + + *offset += count; + return count; +} + +static const struct file_operations last_kmsg_file_ops = { + .owner = THIS_MODULE, + .read = sec_last_kmsg_read, +}; + +static int __init sec_last_kmsg_late_init(void) +{ + struct proc_dir_entry *entry; + + if (!last_kmsg_buffer) + return 0; + + entry = proc_create("last_kmsg", S_IFREG | 0444, + NULL, &last_kmsg_file_ops); + if (!entry) { + pr_err("%s: failed to create proc entry\n", __func__); + return 0; + } + + proc_set_size(entry, last_kmsg_size); + return 0; +} + +late_initcall(sec_last_kmsg_late_init); diff --git a/include/linux/sec_debug.h b/include/linux/sec_debug.h new file mode 100644 index 000000000000..a433d47eedad --- /dev/null +++ b/include/linux/sec_debug.h @@ -0,0 +1,23 @@ +/* +* Samsung debugging features for Samsung's SoC's. +* +* Copyright (c) 2014-2017 Samsung Electronics Co., Ltd. +* http://www.samsung.com +* +* 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; either version 2 of the License, or +* (at your option) any later version. +*/ + +#ifndef SEC_DEBUG_H +#define SEC_DEBUG_H + +#ifdef CONFIG_SEC_DEBUG_LAST_KMSG +#define SEC_LKMSG_MAGICKEY 0x0000000a6c6c7546 +extern void sec_debug_save_last_kmsg(unsigned char *head_ptr, + unsigned char *curr_ptr, size_t buf_size); +#endif + +#endif /* SEC_DEBUG_H */ + diff --git a/lib/debug-snapshot.c b/lib/debug-snapshot.c index ea5902d400c7..5bd026e5775b 100644 --- a/lib/debug-snapshot.c +++ b/lib/debug-snapshot.c @@ -36,6 +36,10 @@ #include #endif +#ifdef CONFIG_SEC_DEBUG_LAST_KMSG +#include +#endif + extern void register_hook_logbuf(void (*)(const char *, size_t)); extern void register_hook_logger(void (*)(const char *, const char *, size_t)); @@ -221,8 +225,12 @@ static inline void dbg_snapshot_hook_logbuf(const char *buf, size_t size) if (likely(dss_base.enabled && item->entry.enabled)) { size_t last_buf; - if (dbg_snapshot_check_eob(item, size)) + if (dbg_snapshot_check_eob(item, size)) { item->curr_ptr = item->head_ptr; +#ifdef CONFIG_SEC_DEBUG_LAST_KMSG + *((unsigned long long *)(item->head_ptr + item->entry.size - (size_t)0x08)) = SEC_LKMSG_MAGICKEY; +#endif + } memcpy(item->curr_ptr, buf, size); item->curr_ptr += size; @@ -706,6 +714,12 @@ static void __init dbg_snapshot_fixmap(void) /* output the information of debug-snapshot */ dbg_snapshot_output(); + +#ifdef CONFIG_SEC_DEBUG_LAST_KMSG + sec_debug_save_last_kmsg(dss_items[dss_desc.log_kernel_num].head_ptr, + dss_items[dss_desc.log_kernel_num].curr_ptr, + dss_items[dss_desc.log_kernel_num].entry.size); +#endif } static int dbg_snapshot_init_dt_parse(struct device_node *np) -- 2.20.1