tzlog_dump: make tzlog dump a module
Functionality was previously in the tz_log.c driver provided by qualcomm. Move to a module to avoid tainting vendor kernel code. Change-Id: I034bf341e781ecc0321df1b8871ce58daec9f379 Signed-off-by: Ryan Lattrel <ryanl@motorola.com> Reviewed-on: https://gerrit.mot.com/1108569 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Kenneth Kessler <kennykessler@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
975e0fc2ca
commit
638cb3dd3a
4 changed files with 368 additions and 0 deletions
8
drivers/tzlog_dump/Android.mk
Normal file
8
drivers/tzlog_dump/Android.mk
Normal file
|
@ -0,0 +1,8 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := tzlog_dump.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
5
drivers/tzlog_dump/Kbuild
Normal file
5
drivers/tzlog_dump/Kbuild
Normal file
|
@ -0,0 +1,5 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
|
||||
|
||||
obj-m += tzlog_dump.o
|
10
drivers/tzlog_dump/Makefile
Normal file
10
drivers/tzlog_dump/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
|||
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
|
345
drivers/tzlog_dump/tzlog_dump.c
Normal file
345
drivers/tzlog_dump/tzlog_dump.c
Normal file
|
@ -0,0 +1,345 @@
|
|||
/* Copyright (c) 2011-2015,2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2018 Motorola Mobility LLC
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/msm_ion.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/cma.h>
|
||||
#include <soc/qcom/memory_dump.h>
|
||||
|
||||
/* Check memory_dump.h to verify this is not going over the max or
|
||||
* conflicting with another entry. Also must match BL
|
||||
*/
|
||||
#define MSM_DUMP_DATA_TZ_LOG 0x11F
|
||||
|
||||
#define TZBSP_DIAG_SIZE 0x3000
|
||||
#define TZBSP_MAGIC_NUMBER 0x747A6461
|
||||
#define TZBSP_VERSION 0x90001
|
||||
#define TZBSP_MAX_CPU_COUNT 0x08
|
||||
#define TZBSP_DIAG_NUM_OF_VMID 16
|
||||
#define TZBSP_DIAG_VMID_DESC_LEN 7
|
||||
#define TZBSP_DIAG_INT_NUM 64
|
||||
#define TZBSP_MAX_INT_DESC 16
|
||||
#define TZBSP_AES_256_ENCRYPTED_KEY_SIZE 256
|
||||
#define TZBSP_NONCE_LEN 12
|
||||
#define TZBSP_TAG_LEN 16
|
||||
|
||||
struct tzdbg_vmid_t {
|
||||
uint8_t vmid;
|
||||
uint8_t desc[TZBSP_DIAG_VMID_DESC_LEN];
|
||||
};
|
||||
|
||||
struct tzdbg_boot_info_t {
|
||||
uint32_t wb_entry_cnt;
|
||||
uint32_t wb_exit_cnt;
|
||||
uint32_t pc_entry_cnt;
|
||||
uint32_t pc_exit_cnt;
|
||||
uint32_t psci_entry_cnt;
|
||||
uint32_t psci_exit_cnt;
|
||||
uint64_t warm_jmp_addr;
|
||||
uint32_t warm_jmp_instr;
|
||||
};
|
||||
|
||||
struct tzdbg_reset_info_t {
|
||||
uint32_t reset_type;
|
||||
uint32_t reset_cnt;
|
||||
};
|
||||
|
||||
struct tzdbg_int_t {
|
||||
uint16_t int_info;
|
||||
uint8_t avail;
|
||||
uint8_t spare;
|
||||
uint32_t int_num;
|
||||
uint8_t int_desc[TZBSP_MAX_INT_DESC];
|
||||
uint64_t int_count[TZBSP_MAX_CPU_COUNT];
|
||||
};
|
||||
|
||||
struct tzbsp_diag_wakeup_info_t {
|
||||
uint32_t HPPIR;
|
||||
uint32_t AHPPIR;
|
||||
};
|
||||
|
||||
struct tzdbg_log_pos_t {
|
||||
uint16_t wrap;
|
||||
uint16_t offset;
|
||||
};
|
||||
|
||||
struct tzdbg_log_t {
|
||||
struct tzdbg_log_pos_t log_pos;
|
||||
uint8_t log_buf[];
|
||||
};
|
||||
|
||||
struct tzdbg_t {
|
||||
uint32_t magic_num;
|
||||
uint32_t version;
|
||||
uint32_t cpu_count;
|
||||
uint32_t vmid_info_off;
|
||||
uint32_t boot_info_off;
|
||||
uint32_t reset_info_off;
|
||||
uint32_t int_info_off;
|
||||
uint32_t ring_off;
|
||||
uint32_t ring_len;
|
||||
uint32_t wakeup_info_off;
|
||||
struct tzdbg_vmid_t vmid_info[TZBSP_DIAG_NUM_OF_VMID];
|
||||
struct tzdbg_boot_info_t boot_info[TZBSP_MAX_CPU_COUNT];
|
||||
struct tzdbg_reset_info_t reset_info[TZBSP_MAX_CPU_COUNT];
|
||||
uint32_t num_interrupts;
|
||||
struct tzdbg_int_t int_info[TZBSP_DIAG_INT_NUM];
|
||||
struct tzbsp_diag_wakeup_info_t wakeup_info[TZBSP_MAX_CPU_COUNT];
|
||||
uint8_t key[TZBSP_AES_256_ENCRYPTED_KEY_SIZE];
|
||||
uint8_t nonce[TZBSP_NONCE_LEN];
|
||||
uint8_t tag[TZBSP_TAG_LEN];
|
||||
struct tzdbg_log_t ring_buffer;
|
||||
};
|
||||
|
||||
struct tz_dump_platform_data {
|
||||
phys_addr_t mem_address;
|
||||
size_t mem_size;
|
||||
};
|
||||
|
||||
static struct tzdbg_t *tzdbg_data;
|
||||
static struct proc_dir_entry *tzdbg_procfs_file;
|
||||
|
||||
static void tzlog_dump_show_boot_info(struct seq_file *f)
|
||||
{
|
||||
int cpu;
|
||||
int power_collapsed;
|
||||
struct tzdbg_boot_info_t *ptr;
|
||||
|
||||
ptr = (struct tzdbg_boot_info_t *)
|
||||
((u8 *)tzdbg_data + tzdbg_data->boot_info_off);
|
||||
|
||||
seq_printf(f, "\n--- TZ Power Collapse Counters\n");
|
||||
seq_printf(f, " | WarmEntry : WarmExit : TermEntry :");
|
||||
seq_printf(f, " TermExit : PsciEntry : PsciExit : JumpAddr |\n");
|
||||
for (cpu = 0; cpu < tzdbg_data->cpu_count; cpu++) {
|
||||
power_collapsed = ptr->wb_entry_cnt +
|
||||
ptr->pc_exit_cnt - ptr->pc_entry_cnt;
|
||||
if (cpu)
|
||||
power_collapsed--;
|
||||
seq_printf(f, "CPU%d | %8x : %8x : %8x : %8x : %8x : %8x : "
|
||||
"%llx | %sPC\n",
|
||||
cpu,
|
||||
ptr->wb_entry_cnt,
|
||||
ptr->wb_exit_cnt,
|
||||
ptr->pc_entry_cnt,
|
||||
ptr->pc_exit_cnt,
|
||||
ptr->psci_entry_cnt,
|
||||
ptr->psci_exit_cnt,
|
||||
ptr->warm_jmp_addr,
|
||||
power_collapsed ? "IN-" : "NOT-");
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void tzlog_dump_show_log(struct seq_file *f)
|
||||
{
|
||||
struct tzdbg_log_t *log_ptr;
|
||||
const char *log_buf, *p, *start;
|
||||
|
||||
log_buf = (const char *)tzdbg_data + tzdbg_data->ring_off;
|
||||
log_ptr = (struct tzdbg_log_t *)(log_buf -
|
||||
offsetof(struct tzdbg_log_t, log_buf));
|
||||
|
||||
if (log_ptr->log_pos.offset >= tzdbg_data->ring_len)
|
||||
return;
|
||||
seq_printf(f, "--- TZ Log start ---\n");
|
||||
if (log_ptr->log_pos.wrap) {
|
||||
for (start = log_buf + log_ptr->log_pos.offset, p = start;
|
||||
p < (log_buf + tzdbg_data->ring_len); p++) {
|
||||
if (isprint(*p))
|
||||
seq_printf(f, "%c", *p);
|
||||
else if ((p > start) && isprint(*(p-1)))
|
||||
seq_printf(f, "\n");
|
||||
}
|
||||
}
|
||||
for (start = log_buf, p = start;
|
||||
p < (log_buf + log_ptr->log_pos.offset); p++) {
|
||||
if (isprint(*p))
|
||||
seq_printf(f, "%c", *p);
|
||||
else if ((p > start) && isprint(*(p-1)))
|
||||
seq_printf(f, "\n");
|
||||
}
|
||||
seq_printf(f, "\n--- TZ Log end ---\n");
|
||||
}
|
||||
|
||||
static int tzlog_dump_seq_show(struct seq_file *f, void *ptr)
|
||||
{
|
||||
if (!tzdbg_data ||
|
||||
tzdbg_data->magic_num != TZBSP_MAGIC_NUMBER ||
|
||||
tzdbg_data->version != TZBSP_VERSION) {
|
||||
seq_printf(f, "No valid backup\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tzlog_dump_show_boot_info(f);
|
||||
tzlog_dump_show_log(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tzlog_dump_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, tzlog_dump_seq_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations tzlog_dump_operations = {
|
||||
.open = tzlog_dump_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void tzlog_dump_procfs_init(void)
|
||||
{
|
||||
/* /proc/driver/tzlog_dump */
|
||||
tzdbg_procfs_file = proc_create("driver/tzlog_dump",
|
||||
0444, NULL, &tzlog_dump_operations);
|
||||
}
|
||||
|
||||
static void tzlog_dump_table_register(struct device *dev,
|
||||
struct tz_dump_platform_data *pdata)
|
||||
{
|
||||
int err = 0;
|
||||
struct msm_dump_entry dump_entry;
|
||||
struct msm_dump_data *tz_dump_data;
|
||||
|
||||
tz_dump_data = kzalloc(sizeof(struct msm_dump_data),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!tz_dump_data) {
|
||||
dev_err(dev, "Cannot alloc dump data structure.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
tz_dump_data->addr = pdata->mem_address;
|
||||
tz_dump_data->len = pdata->mem_size;
|
||||
dump_entry.id = MSM_DUMP_DATA_TZ_LOG;
|
||||
dump_entry.addr = virt_to_phys(tz_dump_data);
|
||||
err = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
|
||||
if (err) {
|
||||
dev_err(dev, "Registering dump data failed.\n");
|
||||
kfree(tz_dump_data);
|
||||
}
|
||||
err:
|
||||
return;
|
||||
}
|
||||
|
||||
static int tzlog_dump_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct tz_dump_platform_data *pdata;
|
||||
struct resource res;
|
||||
struct device_node *node;
|
||||
int err = 0;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get reserved memory region from Device-tree */
|
||||
node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
if (!node) {
|
||||
dev_err(dev, "No %s specified\n", "memory-region");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = of_address_to_resource(node, 0, &res);
|
||||
of_node_put(node);
|
||||
if (err) {
|
||||
dev_err(dev, "No memory address assigned to the region\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
pdata->mem_size = resource_size(&res);
|
||||
pdata->mem_address = res.start;
|
||||
|
||||
dev_info(dev, "tzlog_dump_size %lx", pdata->mem_size);
|
||||
dev_info(dev, "tzlog_dump_addr %lx", (unsigned long)pdata->mem_address);
|
||||
|
||||
if (pdata->mem_size < TZBSP_DIAG_SIZE) {
|
||||
dev_err(dev, "Mem reserve too small %zx/%xu\n",
|
||||
pdata->mem_size, TZBSP_DIAG_SIZE);
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
tzlog_dump_table_register(dev, pdata);
|
||||
|
||||
tzdbg_data = dma_remap(dev, NULL, pdata->mem_address,
|
||||
pdata->mem_size, 0);
|
||||
|
||||
if (!tzdbg_data) {
|
||||
dev_err(dev, "Cannot remap buffer %pa size %zx\n",
|
||||
&pdata->mem_address, pdata->mem_size);
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
tzlog_dump_procfs_init();
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tzlog_dump_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (tzdbg_procfs_file)
|
||||
remove_proc_entry("driver/tzlog_dump", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tzlog_dump_match[] = {
|
||||
{ .compatible = "mmi,tzlog-dump" },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver tzlog_dump_driver = {
|
||||
.probe = tzlog_dump_probe,
|
||||
.remove = tzlog_dump_remove,
|
||||
.driver = {
|
||||
.name = "tzlog_dump",
|
||||
.of_match_table = tzlog_dump_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tzlog_dump_init(void)
|
||||
{
|
||||
return platform_driver_register(&tzlog_dump_driver);
|
||||
}
|
||||
|
||||
static void __exit tzlog_dump_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tzlog_dump_driver);
|
||||
}
|
||||
|
||||
module_init(tzlog_dump_init);
|
||||
module_exit(tzlog_dump_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("TZ Log dump driver");
|
Loading…
Reference in a new issue