/* SPDX-License-Identifier: GPL-2.0-only */ /* * drivers/debug/sec_debug_internal.h * * COPYRIGHT(C) 2020 Samsung Electronics Co., Ltd. All Right Reserved. * */ #ifndef __SEC_DEBUG_INTERNAL_H__ #define __SEC_DEBUG_INTERNAL_H__ #include #include #include /* TODO: SoC dependent offset, get them from LSI code ? */ #define EXYNOS_PMU_INFORM2 0x0808 #define EXYNOS_PMU_INFORM3 0x080C /* AP SFR to send some information from kernel to bootloader */ #define SEC_DEBUG_MAGIC_INFORM (EXYNOS_PMU_INFORM2) #define SEC_DEBUG_PANIC_INFORM (EXYNOS_PMU_INFORM3) /* RESET REASON */ enum sec_debug_reset_reason_t { RR_S = 1, RR_W = 2, RR_D = 3, RR_K = 4, RR_M = 5, RR_P = 6, RR_R = 7, RR_B = 8, RR_N = 9, RR_T = 10, RR_C = 11, }; /* sec debug buffer format */ struct outbuf { char buf[SZ_1K]; int index; int already; }; /* for sub data-structure of SDN */ struct sec_debug_ksyms { uint32_t magic; uint32_t kallsyms_all; uint64_t addresses_pa; uint64_t names_pa; uint64_t num_syms; uint64_t token_table_pa; uint64_t token_index_pa; uint64_t markers_pa; struct ksect { uint64_t sinittext; uint64_t einittext; uint64_t stext; uint64_t etext; uint64_t end; } sect; uint64_t relative_base; uint64_t offsets_pa; uint64_t kimage_voffset; uint64_t reserved[4]; }; /* kcnst has some kernel constant (offset) data for bootloader */ struct basic_type_int { uint64_t pa; /* physical address of the variable */ uint32_t size; /* size of basic type. eg sizeof(unsigned long) goes here */ uint32_t count; /* for array types */ }; struct sec_debug_kcnst { uint64_t nr_cpus; struct basic_type_int per_cpu_offset; uint64_t phys_offset; uint64_t phys_mask; uint64_t page_offset; uint64_t page_mask; uint64_t page_shift; uint64_t va_bits; uint64_t kimage_vaddr; uint64_t kimage_voffset; uint64_t pa_swapper; uint64_t pgdir_shift; uint64_t pud_shift; uint64_t pmd_shift; uint64_t ptrs_per_pgd; uint64_t ptrs_per_pud; uint64_t ptrs_per_pmd; uint64_t ptrs_per_pte; uint64_t kconfig_base; uint64_t kconfig_size; uint64_t pa_text; uint64_t pa_start_rodata; uint64_t target_dprm_mask; uint64_t reserved[3]; }; struct member_type { uint16_t size; uint16_t offset; }; typedef struct member_type member_type_int; typedef struct member_type member_type_long; typedef struct member_type member_type_longlong; typedef struct member_type member_type_ptr; typedef struct member_type member_type_str; struct struct_thread_info { uint32_t struct_size; member_type_long flags; member_type_ptr task; member_type_int cpu; member_type_long rrk; }; struct struct_task_struct { uint32_t struct_size; member_type_long state; member_type_long exit_state; member_type_ptr stack; member_type_int flags; member_type_int on_cpu; member_type_int on_rq; member_type_int cpu; member_type_int pid; member_type_str comm; member_type_ptr tasks_next; member_type_ptr thread_group_next; member_type_long fp; member_type_long sp; member_type_long pc; member_type_long sched_info__pcount; member_type_longlong sched_info__run_delay; member_type_longlong sched_info__last_arrival; member_type_longlong sched_info__last_queued; member_type_int ssdbg_wait__type; member_type_ptr ssdbg_wait__data; }; struct irq_stack_info { uint64_t pcpu_stack; /* IRQ_STACK_PTR(0) */ uint64_t size; /* IRQ_STACK_SIZE */ uint64_t start_sp; /* IRQ_STACK_START_SP */ }; /* task_struct offset data */ struct sec_debug_task { uint64_t stack_size; /* THREAD_SIZE */ uint64_t start_sp; /* TRHEAD_START_SP */ struct struct_thread_info ti; struct struct_task_struct ts; uint64_t init_task; struct irq_stack_info irq_stack; }; #define SD_NR_ESSINFO_ITEMS (16) /* Exynos Debug Snapshot offset data */ struct sec_debug_ess_info { struct ess_info_offset item[SD_NR_ESSINFO_ITEMS]; }; /* Watchdog driver data */ struct watchdogd_info { struct task_struct *tsk; struct thread_info *thr; struct rtc_time *tm; unsigned long long last_ping_time; int last_ping_cpu; bool init_done; unsigned long emerg_addr; }; struct bad_stack_info { unsigned long magic; unsigned long esr; unsigned long far; unsigned long spel0; unsigned long cpu; unsigned long tsk_stk; unsigned long irq_stk; unsigned long ovf_stk; }; struct suspend_dev_info { uint64_t suspend_func; uint64_t suspend_device; uint64_t shutdown_func; uint64_t shutdown_device; }; struct sec_debug_kernel_data { uint64_t task_in_pm_suspend; uint64_t task_in_sys_reboot; uint64_t task_in_sys_shutdown; uint64_t task_in_dev_shutdown; uint64_t task_in_sysrq_crash; uint64_t task_in_soft_lockup; uint64_t cpu_in_soft_lockup; uint64_t task_in_hard_lockup; uint64_t cpu_in_hard_lockup; uint64_t unfrozen_task; uint64_t unfrozen_task_count; uint64_t sync_irq_task; uint64_t sync_irq_num; uint64_t sync_irq_name; uint64_t sync_irq_desc; uint64_t sync_irq_thread; uint64_t sync_irq_threads_active; uint64_t dev_shutdown_start; uint64_t dev_shutdown_end; uint64_t dev_shutdown_duration; uint64_t dev_shutdown_func; unsigned long sysrq_ptr; struct watchdogd_info wddinfo; struct bad_stack_info bsi; struct suspend_dev_info sdi; }; /* some buffers to use in sec debug module */ enum sdn_map { SDN_MAP_DUMP_SUMMARY, SDN_MAP_AUTO_COMMENT, SDN_MAP_EXTRA_INFO, SDN_MAP_AUTO_ANALYSIS, SDN_MAP_INITTASK_LOG, SDN_MAP_DEBUG_PARAM, SDN_MAP_FIRST2M_LOG, SDN_MAP_SPARED_BUFFER, NR_SDN_MAP, }; struct sec_debug_buf { unsigned long base; unsigned long size; }; struct sec_debug_map { struct sec_debug_buf buf[NR_SDN_MAP]; }; /* macro to initialize kernel data structure offset data */ #define SET_MEMBER_TYPE_INFO(PTR, TYPE, MEMBER) \ { \ (PTR)->size = sizeof(((TYPE *)0)->MEMBER); \ (PTR)->offset = offsetof(TYPE, MEMBER); \ } struct sec_debug_memtab { uint64_t table_start_pa; uint64_t table_end_pa; uint64_t reserved[4]; }; #define THREAD_START_SP (THREAD_SIZE - 16) #define IRQ_STACK_START_SP THREAD_START_SP #define SEC_DEBUG_MAGIC0 (0x11221133) #define SEC_DEBUG_MAGIC1 (0x12121313) /* TODO: sdn needs extra info data structure to define it normally, but ... */ /* ------------------------------------------------ * SEC DEBUG EXTRA INFO * ------------------------------------------------ */ enum shared_buffer_slot { SLOT_32, SLOT_64, SLOT_256, SLOT_1024, SLOT_MAIN_END = SLOT_1024, NR_MAIN_SLOT = 4, SLOT_BK_32 = NR_MAIN_SLOT, SLOT_BK_64, SLOT_BK_256, SLOT_BK_1024, SLOT_END = SLOT_BK_1024, NR_SLOT = 8, }; struct sec_debug_sb_index { unsigned int paddr; /* physical address of slot */ unsigned int size; /* size of a item */ unsigned int nr; /* number of items in slot */ unsigned int cnt; /* number of used items in slot */ /* map to indicate which items are added by bootloader */ unsigned long blmark; }; struct sec_debug_shared_buffer { /* initial magic code */ unsigned int magic[4]; /* shared buffer index */ struct sec_debug_sb_index sec_debug_sbidx[NR_SLOT]; }; /* TODO: sdn needs auto comment data structure to define it normally, but ... */ /* ------------------------------------------------ * SEC DEBUG AUTO COMMENT * ------------------------------------------------ */ #define SEC_DEBUG_AUTO_COMM_BUF_SIZE 10 struct sec_debug_auto_comm_buf { int reserved_0; int reserved_1; int reserved_2; unsigned int offset; char buf[SZ_4K]; }; struct sec_debug_auto_comment { int header_magic; int fault_flag; int lv5_log_cnt; u64 lv5_log_order; int order_map_cnt; int order_map[SEC_DEBUG_AUTO_COMM_BUF_SIZE]; struct sec_debug_auto_comm_buf auto_comm_buf[SEC_DEBUG_AUTO_COMM_BUF_SIZE]; int tail_magic; }; /* ------------------------------------------------ * SEC DEBUG GEN3 (Compatible with SEC DEBUG NEXT) * ------------------------------------------------ */ #define SEC_DEBUG_GEN3_MAGIC0 (0xc3a50421) #define SEC_DEBUG_GEN3_MAGIC1 (0xe2b42021) #define LEN_SECDBG_OFFSET_NAME (64) struct sec_debug_version { unsigned int magic[2]; unsigned int version[2]; }; #define NR_GEN3_LOGBUF 32 #define NR_GEN3_KEVENT 32 /* LV1 */ struct secdbg_extra_info { struct sec_debug_shared_buffer data; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_auto_comment { struct sec_debug_auto_comment data; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_kernel_data { struct sec_debug_kernel_data data; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_snapshot_offset { struct ess_info_offset data[NR_GEN3_KEVENT]; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_task_struct { struct sec_debug_task data; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_kernel_constant { struct sec_debug_kcnst data; char name[LEN_SECDBG_OFFSET_NAME]; }; #define LEN_LOGBUF_NAME (32) /* LV2 (under secdbg_logbuf_list) */ struct secdbg_logbuf { uint64_t base; uint64_t size; char name[LEN_LOGBUF_NAME]; uint32_t is_storage; uint32_t offset; uint32_t partition; }; /* LV1 */ struct secdbg_logbuf_list { struct secdbg_logbuf data[NR_GEN3_LOGBUF]; char name[LEN_SECDBG_OFFSET_NAME]; }; /* LV1 */ struct secdbg_memtab { struct sec_debug_memtab data; char name[LEN_SECDBG_OFFSET_NAME]; }; /* Offset for LV1 */ struct secdbg_lv1_member { char name[LEN_SECDBG_OFFSET_NAME]; uint64_t size; uint64_t addr; }; enum gen3_lv1_item { SDN_LV1_LOGBUF_MAP, SDN_LV1_MEMTAB, SDN_LV1_KERNEL_SYMBOL, SDN_LV1_KERNEL_CONSTANT, SDN_LV1_TASK_STRUCT, SDN_LV1_SNAPSHOT, SDN_LV1_SPINLOCK, /* reserved */ SDN_LV1_KERNEL_DATA, SDN_LV1_AUTO_COMMENT, SDN_LV1_EXTRA_INFO, }; /* increase if sec_debug_next is not changed and other feature is upgraded */ #define SEC_DEBUG_KERNEL_UPPER_VERSION (0x1001) /* increase if sec_debug_next is changed */ #define SEC_DEBUG_KERNEL_LOWER_VERSION (0x1002) /* SEC DEBUG NEXT DEFINITION */ struct sec_debug_gen3 { unsigned int magic[2]; unsigned int version[2]; unsigned int used_offset; unsigned int end_addr; unsigned int reserved[4]; struct secdbg_lv1_member lv1_data[64]; }; struct sec_debug_base_param { void *sdn_vaddr; bool init_sdn_done; }; /* SEC DEBUG HARDLOCUP INFO */ enum ehld_types { NO_INSTRET, NO_INSTRUN, MAX_ETYPES }; #if IS_ENABLED(CONFIG_SEC_DEBUG_MEMTAB) extern struct secdbg_member_type __start__secdbg_member_table[]; extern struct secdbg_member_type __stop__secdbg_member_table[]; #endif /* function for external call */ extern void *secdbg_base_get_debug_base(int type); extern unsigned long secdbg_base_get_buf_base(int type); extern unsigned long secdbg_base_get_buf_size(int type); extern void *secdbg_base_get_ncva(unsigned long pa); extern unsigned long secdbg_base_get_end_addr(void); extern void *secdbg_base_get_kcnst_base(void); extern int secdbg_part_init_bdev_path(struct device *dev); #if IS_ENABLED(CONFIG_SEC_DEBUG_LOCKUP_INFO) void secdbg_base_set_info_hard_lockup(unsigned int cpu, struct task_struct *task); #endif /* SEC DEBUG EXTAR INFO */ #define MAX_ITEM_KEY_LEN (16) #define MAX_ITEM_VAL_LEN (1008) #define SEC_DEBUG_SHARED_MAGIC0 0xFFFFFFFF #define SEC_DEBUG_SHARED_MAGIC1 0x95308180 #define SEC_DEBUG_SHARED_MAGIC2 0x15001500 #define SEC_DEBUG_SHARED_MAGIC3 0x00010001 extern int id_get_asb_ver(void); extern int id_get_product_line(void); extern char *get_bk_item_val(const char *key); extern void get_bk_item_val_as_string(const char *key, char *buf); extern void secdbg_exin_set_hwid(int asb_ver, int psite, const char *dramstr); extern void secdbg_exin_get_extra_info_A(char *ptr); extern void secdbg_exin_get_extra_info_B(char *ptr); extern void secdbg_exin_get_extra_info_C(char *ptr); extern void secdbg_exin_get_extra_info_F(char *ptr); extern void secdbg_exin_get_extra_info_M(char *ptr); extern void secdbg_exin_get_extra_info_T(char *ptr); int secdbg_atsl_init(void); #ifndef MODULE extern void *secdbg_base_built_get_debug_base(int type); extern unsigned long secdbg_base_built_get_buf_base(int type); extern unsigned long secdbg_base_built_get_buf_size(int type); extern void *secdbg_base_built_get_ncva(unsigned long pa); #if IS_ENABLED(CONFIG_SEC_DEBUG_AUTO_COMMENT) extern int secdbg_comm_auto_comment_init(void); #else static inline int secdbg_comm_auto_comment_init(void) { return 0; } #endif /* CONFIG_SEC_DEBUG_AUTO_COMMENT */ #if IS_ENABLED(CONFIG_SEC_DEBUG_EXTRA_INFO_BUILT_IN) extern int secdbg_extra_info_built_init(void); #else static inline int secdbg_extra_info_built_init(void) { return 0; } #endif /* CONFIG_SEC_DEBUG_EXTRA_INFO */ #endif /* !MODULE */ extern void secdbg_ksym_set_kallsyms_info(struct sec_debug_ksyms *ksyms); /* sec_debug_memtab_built.c */ #if IS_ENABLED(CONFIG_SEC_DEBUG_MEMTAB) extern void secdbg_base_built_set_memtab_info(struct sec_debug_memtab *mtab); #else static inline void secdbg_base_built_set_memtab_info(struct sec_debug_memtab *mtab) { } #endif #if IS_ENABLED(CONFIG_SEC_DEBUG_STACKTRACE) extern void secdbg_stra_show_callstack_auto(struct task_struct *tsk); #else static inline void secdbg_stra_show_callstack_auto(struct task_struct *tsk) {} #endif #if IS_ENABLED(CONFIG_SEC_DEBUG_COREDUMP) extern void register_coredump_hook_notes_write(int (*func)(struct coredump_params *)); extern void register_coredump_hook_notes_size(int (*func)(void)); #else static inline void register_coredump_hook_notes_write(int (*func)(struct coredump_params *)) { } static inline void register_coredump_hook_notes_size(int (*func)(void)) { } #endif #endif /* __SEC_DEBUG_INTERNAL_H__ */