implement samsung last_kmsg
authorStricted <info@stricted.net>
Mon, 20 Apr 2020 13:09:23 +0000 (13:09 +0000)
committerStricted <info@stricted.net>
Fri, 24 Apr 2020 18:04:08 +0000 (18:04 +0000)
drivers/staging/samsung/Kconfig
drivers/staging/samsung/Makefile
drivers/staging/samsung/sec_debug_last_kmsg.c [new file with mode: 0644]
include/linux/sec_debug.h [new file with mode: 0644]
lib/debug-snapshot.c

index c050fdfe10bb25413edafdc4ee751f53e9623c4d..f256c252ddb3cd0fa6953d6c0fa90766b5386c96 100644 (file)
@@ -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
index a6bd573d311f49ea5f469f76d2a093ca2d9e749e..b50cb3f2d2ee919bccda13734dfa45fbe328b7ea 100644 (file)
@@ -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 (file)
index 0000000..37247d5
--- /dev/null
@@ -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 <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/sec_debug.h>
+
+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 (file)
index 0000000..a433d47
--- /dev/null
@@ -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 */
+
index ea5902d400c78fab7aeb007e3dd89b84a4dbdd07..5bd026e5775b5fa80a8246763ef44c80462aa696 100644 (file)
 #include <soc/samsung/cal-if.h>
 #endif
 
+#ifdef CONFIG_SEC_DEBUG_LAST_KMSG
+#include <linux/sec_debug.h>
+#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)