diff --git a/arch/arm64/configs/vendor/pineapple_GKI.config b/arch/arm64/configs/vendor/pineapple_GKI.config index 86b181985880..17e2414ec7bd 100644 --- a/arch/arm64/configs/vendor/pineapple_GKI.config +++ b/arch/arm64/configs/vendor/pineapple_GKI.config @@ -62,6 +62,8 @@ CONFIG_MHI_BUS=m CONFIG_MHI_BUS_MISC=y CONFIG_MHI_SATELLITE=m CONFIG_MHI_UCI=m +# CONFIG_MINIDUMP_ALL_TASK_INFO is not set +CONFIG_MINIDUMP_MAX_ENTRIES=200 CONFIG_MMC_SDHCI_MSM=m # CONFIG_MODULE_SIG_ALL is not set CONFIG_MSM_BOOT_STATS=m @@ -102,6 +104,7 @@ CONFIG_QCOM_CRM=m CONFIG_QCOM_DCC_V2=m CONFIG_QCOM_DCVS=m CONFIG_QCOM_DCVS_FP=m +CONFIG_QCOM_DEBUG_SYMBOL=m CONFIG_QCOM_DMABUF_HEAPS=m CONFIG_QCOM_DMABUF_HEAPS_CARVEOUT=y CONFIG_QCOM_DMABUF_HEAPS_CMA=y @@ -109,6 +112,7 @@ CONFIG_QCOM_DMABUF_HEAPS_PAGE_POOL_REFILL=y CONFIG_QCOM_DMABUF_HEAPS_SYSTEM=y CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_SECURE=y CONFIG_QCOM_DMABUF_HEAPS_UBWCP=y +# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set CONFIG_QCOM_EUD=m CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y CONFIG_QCOM_GDSC_REGULATOR=m @@ -132,7 +136,10 @@ CONFIG_QCOM_MEM_BUF_DEV_GH=y CONFIG_QCOM_MEM_BUF_GH=y CONFIG_QCOM_MEM_BUF_MSGQ=m CONFIG_QCOM_MEM_OFFLINE=m -# CONFIG_QCOM_MINIDUMP is not set +CONFIG_QCOM_MINIDUMP=m +# CONFIG_QCOM_MINIDUMP_FTRACE is not set +# CONFIG_QCOM_MINIDUMP_PANIC_DUMP is not set +# CONFIG_QCOM_MINIDUMP_PSTORE is not set CONFIG_QCOM_PANEL_EVENT_NOTIFIER=m CONFIG_QCOM_PANIC_ON_NOTIF_TIMEOUT=y CONFIG_QCOM_PANIC_ON_PDR_NOTIF_TIMEOUT=y @@ -168,6 +175,7 @@ CONFIG_QCOM_SPSS=m CONFIG_QCOM_STATS=m CONFIG_QCOM_TSENS=m CONFIG_QCOM_VADC_COMMON=m +# CONFIG_QCOM_VA_MINIDUMP is not set CONFIG_QCOM_WATCHDOG_BARK_TIME=11000 CONFIG_QCOM_WATCHDOG_IPI_PING=y CONFIG_QCOM_WATCHDOG_PET_TIME=9360 diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6f1f69150cae..95e43a3f3663 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -825,6 +825,14 @@ config QCOM_ICC_BWMON the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high memory throughput even with lower CPU frequencies. +config QCOM_DEBUG_SYMBOL + tristate "Enable Debug Symbol Support" + help + This enables Debug Symbol Support. This driver is based on + Google Debug Kinfo driver, according to the provided info, this + driver allows other modules to get symbol addresses by traversing + kallsyms table for debug usage. + source "drivers/soc/qcom/mem_buf/Kconfig" source "drivers/soc/qcom/tmecom/Kconfig" diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 4f4114464532..2e39766b86d4 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -80,3 +80,4 @@ wcd_usbss_i2c-y += wcd-usbss-tables.o wcd_usbss_i2c-y += wcd-usbss-utils.o wcd_usbss_i2c-y += wcd939x-i2c.o obj-$(CONFIG_QCOM_PANEL_EVENT_NOTIFIER) += panel_event_notifier.o +obj-$(CONFIG_QCOM_DEBUG_SYMBOL) += debug_symbol.o diff --git a/drivers/soc/qcom/debug_symbol.c b/drivers/soc/qcom/debug_symbol.c new file mode 100644 index 000000000000..9aea3fe8a7eb --- /dev/null +++ b/drivers/soc/qcom/debug_symbol.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * kallsyms.c: in-kernel printing of symbolic oopses and stack traces. + * + * Rewritten and vastly simplified by Rusty Russell for in-kernel + * module loader: + * Copyright 2002 Rusty Russell IBM Corporation + * + * ChangeLog: + * + * (25/Aug/2004) Paulo Marques + * Changed the compression method from stem compression to "table lookup" + * compression (see scripts/kallsyms.c for a more complete description) + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * This driver is based on Google Debug Kinfo Driver + */ + +#define pr_fmt(fmt) "DebugSymbol: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "debug_symbol.h" +#include "../../android/debug_kinfo.h" + +struct debug_symbol_data { + const unsigned long *addresses; + const int *offsets; + const u8 *names; + unsigned int num_syms; + unsigned long relative_base; + const char *token_table; + const u16 *token_index; + const unsigned int *markers; +}; + +static struct debug_symbol_data debug_symbol; +static void *debug_symbol_vaddr; + +int debug_symbol_available(void) +{ + struct kernel_all_info *kainfo; + struct kernel_info *kinfo; + + if (!debug_symbol_vaddr) + return -EINVAL; + + kainfo = (struct kernel_all_info *)debug_symbol_vaddr; + kinfo = &(kainfo->info); + + if (kainfo->magic_number != DEBUG_KINFO_MAGIC) { + pr_debug("debug_symbol is not available now\n"); + return -EPROBE_DEFER; + } + + if (!debug_symbol.addresses) { + debug_symbol.addresses = (unsigned long *) + __phys_to_kimg(kinfo->_addresses_pa); + debug_symbol.offsets = (int *) + __phys_to_kimg(kinfo->_offsets_pa); + debug_symbol.names = (u8 *) + __phys_to_kimg(kinfo->_names_pa); + debug_symbol.num_syms = kinfo->num_syms; + debug_symbol.relative_base = + __phys_to_kimg(kinfo->_relative_pa); + debug_symbol.token_table = (char *) + __phys_to_kimg(kinfo->_token_table_pa); + debug_symbol.token_index = (u16 *) + __phys_to_kimg(kinfo->_token_index_pa); + debug_symbol.markers = (unsigned int *) + __phys_to_kimg(kinfo->_markers_pa); + } + + return 0; +} +EXPORT_SYMBOL(debug_symbol_available); + +/* In line with kallsyms_expand_symbol from kernel/kallsyms.c */ +static unsigned int debug_symbol_expand_symbol(unsigned int off, + char *result, size_t maxlen) +{ + int len, skipped_first = 0; + const char *tptr; + const u8 *data; + + data = &debug_symbol.names[off]; + len = *data; + data++; + + off += len + 1; + + while (len) { + tptr = &debug_symbol.token_table[debug_symbol.token_index[*data]]; + data++; + len--; + + while (*tptr) { + if (skipped_first) { + if (maxlen <= 1) + goto tail; + *result = *tptr; + result++; + maxlen--; + } else + skipped_first = 1; + tptr++; + } + } + +tail: + if (maxlen) + *result = '\0'; + + return off; +} + +/* In line with kallsyms_sym_address from kernel/kallsyms.c */ +static unsigned long debug_symbol_sym_address(int idx) +{ + if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE)) + return debug_symbol.addresses[idx]; + + if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU)) + return debug_symbol.relative_base + (u32)debug_symbol.offsets[idx]; + + if (debug_symbol.offsets[idx] >= 0) + return debug_symbol.offsets[idx]; + + return debug_symbol.relative_base - 1 - debug_symbol.offsets[idx]; +} + +/* In line with cleanup_symbol_name from kernel/kallsyms.c */ +static bool cleanup_symbol_name(char *s) +{ + char *res; + + if (!IS_ENABLED(CONFIG_LTO_CLANG)) + return false; + + res = strnchr(s, KSYM_NAME_LEN, '.'); + if (res) { + *res = '\0'; + return true; + } + + if (!IS_ENABLED(CONFIG_CFI_CLANG) || + !IS_ENABLED(CONFIG_LTO_CLANG_THIN) || + CONFIG_CLANG_VERSION >= 130000) + return false; + + res = strrchr(s, '$'); + if (res) { + *res = '\0'; + return true; + } + + return false; +} + +/* In line with kallsyms_lookup_name from kernel/kallsyms.c */ +unsigned long debug_symbol_lookup_name(const char *name) +{ + char namebuf[KSYM_NAME_LEN]; + unsigned long i; + unsigned int off; + + if (!*name) + return 0; + + for (i = 0, off = 0; i < debug_symbol.num_syms; i++) { + off = debug_symbol_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); + + if (strcmp(namebuf, name) == 0) + return debug_symbol_sym_address(i); + + if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0) + return debug_symbol_sym_address(i); + } + return 0; +} +EXPORT_SYMBOL(debug_symbol_lookup_name); + +static int __init debug_symbol_init(void) +{ + struct device_node *rmem_node; + struct reserved_mem *rmem; + + rmem_node = of_find_compatible_node(NULL, NULL, "google,debug-kinfo"); + if (!rmem_node) { + pr_err("cannot get compatible node\n"); + goto out; + } + + rmem_node = of_parse_phandle(rmem_node, "memory-region", 0); + if (!rmem_node) { + pr_err("cannot get memory region\n"); + goto out; + } + + rmem = of_reserved_mem_lookup(rmem_node); + if (!rmem) { + pr_err("cannot get reserved memory\n"); + goto out; + } + + debug_symbol_vaddr = memremap(rmem->base, rmem->size, MEMREMAP_WB); + if (!debug_symbol_vaddr) { + pr_err("failed to map reserved memory\n"); + goto out; + } + + memset(debug_symbol_vaddr, 0, sizeof(struct kernel_all_info)); + rmem->priv = debug_symbol_vaddr; + +out: + return 0; +} +arch_initcall(debug_symbol_init); + +MODULE_DESCRIPTION("QCOM Debug Symbol driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/qcom/debug_symbol.h b/drivers/soc/qcom/debug_symbol.h new file mode 100644 index 000000000000..376d32c67aeb --- /dev/null +++ b/drivers/soc/qcom/debug_symbol.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + */ + +#ifndef _DEBUG_SYMBOL_H +#define _DEBUG_SYMBOL_H + +#include + +#if IS_ENABLED(CONFIG_QCOM_DEBUG_SYMBOL) +extern int debug_symbol_available(void); +extern unsigned long debug_symbol_lookup_name(const char *name); +#else +static inline int debug_symbol_available(void) +{ + return -EINVAL; +} + +static inline unsigned long debug_symbol_lookup_name(const char *name) +{ + return 0; +} +#endif /* CONFIG_QCOM_DEBUG_SYMBOL */ + +#endif diff --git a/drivers/soc/qcom/minidump_log.c b/drivers/soc/qcom/minidump_log.c index 4e9f024be4c8..9a63423d4625 100644 --- a/drivers/soc/qcom/minidump_log.c +++ b/drivers/soc/qcom/minidump_log.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include "debug_symbol.h" #ifdef CONFIG_QCOM_MINIDUMP_PSTORE #include #include @@ -195,10 +195,10 @@ static void register_kernel_sections(void) void *_sdata, *__bss_stop; void *start_ro, *end_ro; - _sdata = android_debug_symbol(ADS_SDATA); - __bss_stop = android_debug_symbol(ADS_BSS_END); - base = android_debug_symbol(ADS_PER_CPU_START); - static_size = (size_t)(android_debug_symbol(ADS_PER_CPU_END) - base); + _sdata = (void *)debug_symbol_lookup_name("_sdata"); + __bss_stop = (void *)debug_symbol_lookup_name("__bss_stop"); + base = (void *)debug_symbol_lookup_name("__per_cpu_start"); + static_size = (size_t)((void *)debug_symbol_lookup_name("__per_cpu_end") - base); strscpy(ksec_entry.name, data_name, sizeof(ksec_entry.name)); ksec_entry.virt_addr = (u64)_sdata; @@ -207,8 +207,8 @@ static void register_kernel_sections(void) if (msm_minidump_add_region(&ksec_entry) < 0) pr_err("Failed to add data section in Minidump\n"); - start_ro = android_debug_symbol(ADS_START_RO_AFTER_INIT); - end_ro = android_debug_symbol(ADS_END_RO_AFTER_INIT); + start_ro = (void *)debug_symbol_lookup_name("__start_ro_after_init"); + end_ro = (void *)debug_symbol_lookup_name("__end_ro_after_init"); strscpy(ksec_entry.name, rodata_name, sizeof(ksec_entry.name)); ksec_entry.virt_addr = (uintptr_t)start_ro; ksec_entry.phys_addr = virt_to_phys(start_ro); @@ -567,7 +567,7 @@ static void register_irq_stack(void) u64 irq_stack_base; struct md_region irq_sp_entry; u64 sp; - u64 *irq_stack_ptr = android_debug_per_cpu_symbol(ADS_IRQ_STACK_PTR); + u64 *irq_stack_ptr = (void *)debug_symbol_lookup_name("irq_stack_ptr"); for_each_possible_cpu(cpu) { irq_stack_base = *(u64 *)(per_cpu_ptr((void *)irq_stack_ptr, cpu)); diff --git a/drivers/soc/qcom/msm_minidump.c b/drivers/soc/qcom/msm_minidump.c index 1f50acdaf874..7e45b9255e09 100644 --- a/drivers/soc/qcom/msm_minidump.c +++ b/drivers/soc/qcom/msm_minidump.c @@ -17,10 +17,10 @@ #include #include #include -#include #include #include #include +#include "debug_symbol.h" #include "minidump_private.h" #include "elf.h" @@ -833,7 +833,7 @@ static int msm_minidump_add_header(void) char *banner, *linux_banner; int slot_num; - linux_banner = android_debug_symbol(ADS_LINUX_BANNER); + linux_banner = (void *)debug_symbol_lookup_name("linux_banner"); /* Header buffer contains: * elf header, MAX_NUM_ENTRIES+4 of section and program elf headers, * string table section and linux banner. @@ -963,6 +963,9 @@ static int msm_minidump_driver_probe(struct platform_device *pdev) unsigned long flags; int ret; + if (debug_symbol_available()) + return -EPROBE_DEFER; + is_rm_minidump = of_device_is_compatible(pdev->dev.of_node, "qcom,minidump-rm"); diff --git a/modules.list.msm.pineapple b/modules.list.msm.pineapple index 0151f02b8a4f..936d63dd1ea2 100644 --- a/modules.list.msm.pineapple +++ b/modules.list.msm.pineapple @@ -20,6 +20,8 @@ clk-qcom.ko clk-dummy.ko clk-rpmh.ko dcc_v2.ko +debug_symbol.ko +minidump.ko memory_dump_v2.ko dispcc-pineapple.ko tcsrcc-pineapple.ko