diff --git a/drivers/soc/rockchip/minidump/minidump_log.c b/drivers/soc/rockchip/minidump/minidump_log.c index 8c911827de70..45eb9760da0b 100644 --- a/drivers/soc/rockchip/minidump/minidump_log.c +++ b/drivers/soc/rockchip/minidump/minidump_log.c @@ -659,20 +659,68 @@ static int md_register_minidump_entry(char *name, u64 virt_addr, return ret; } -static int md_is_kernel_address(u64 addr) +struct page *md_vmalloc_to_page(const void *vmalloc_addr) +{ + unsigned long addr = (unsigned long) vmalloc_addr; + struct page *page = NULL; + pgd_t *pgd = pgd_offset_k(addr); + p4d_t *p4d; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep, pte; + + if (pgd_none(*pgd)) + return NULL; + p4d = p4d_offset(pgd, addr); + if (p4d_none(*p4d)) + return NULL; + pud = pud_offset(p4d, addr); + + if (pud_none(*pud) || pud_bad(*pud)) + return NULL; + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return NULL; + + ptep = pte_offset_map(pmd, addr); + pte = *ptep; + if (pte_present(pte)) + page = pte_page(pte); + pte_unmap(ptep); + return page; +} + +static bool md_is_kernel_address(u64 addr) { u32 data; + u64 phys_addr = 0; + struct page *page; - if (addr < PAGE_OFFSET || addr > -4096UL) - return 0; + if (!is_ttbr1_addr(addr)) + return false; if (addr >= (u64)_text && addr < (u64)_end) - return 0; + return false; + + if (__is_lm_address(addr)) { + phys_addr = virt_to_phys((void *)addr); + } else if (is_vmalloc_or_module_addr((const void *)addr)) { + page = md_vmalloc_to_page((const void *) addr); + if (page) + phys_addr = page_to_phys(page); + else + return false; + } else { + return false; + } + + if (!md_is_ddr_address(phys_addr)) + return false; if (aarch64_insn_read((void *)addr, &data)) - return 0; + return false; else - return 1; + return true; } static int md_save_page(u64 addr, bool flush) @@ -689,8 +737,8 @@ static int md_save_page(u64 addr, bool flush) if (__is_lm_address(virt_addr)) { phys_addr = virt_to_phys((void *)virt_addr); - } else if (virt_addr >= VMALLOC_START && virt_addr < VMALLOC_END) { - page = vmalloc_to_page((const void *) virt_addr); + } else if (is_vmalloc_or_module_addr((const void *)virt_addr)) { + page = md_vmalloc_to_page((const void *) virt_addr); phys_addr = page_to_phys(page); } else { return -1; diff --git a/drivers/soc/rockchip/minidump/minidump_memory.c b/drivers/soc/rockchip/minidump/minidump_memory.c index 95fc78aa1e69..d7f93e2f12b6 100644 --- a/drivers/soc/rockchip/minidump/minidump_memory.c +++ b/drivers/soc/rockchip/minidump/minidump_memory.c @@ -933,7 +933,7 @@ static ssize_t slab_owner_dump_size_read(struct file *file, char __user *ubuf, { char buf[100]; - snprintf(buf, sizeof(buf), "%llu MB\n", md_slabowner_dump_size/SZ_1M); + snprintf(buf, sizeof(buf), "%lu MB\n", md_slabowner_dump_size/SZ_1M); return simple_read_from_buffer(ubuf, count, offset, buf, strlen(buf)); } diff --git a/drivers/soc/rockchip/minidump/rk_minidump.c b/drivers/soc/rockchip/minidump/rk_minidump.c index 0f90fce431e2..d742b7e2eda6 100644 --- a/drivers/soc/rockchip/minidump/rk_minidump.c +++ b/drivers/soc/rockchip/minidump/rk_minidump.c @@ -72,6 +72,8 @@ static bool md_init_done; static void __iomem *md_elf_mem; static resource_size_t md_elf_size; static struct proc_dir_entry *proc_rk_minidump; +static bool md_is_ddr_address_default(u64 phys_addr); +bool (*md_is_ddr_address)(u64 virt_addr) = md_is_ddr_address_default; /* Number of pending entries to be added in ToC regions */ static unsigned int pendings; @@ -621,6 +623,22 @@ static const struct proc_ops rk_minidump_proc_ops = { .proc_read = rk_minidump_read_elf, }; +static bool md_is_ddr_address_rk3588(u64 phys_addr) +{ + /* peripheral address space */ + if (phys_addr >= 0xf0000000 && phys_addr < 0x100000000) + return false; + /* DDR is up to 32GB */ + if (phys_addr > 0x800000000) + return false; + return true; +} + +static bool md_is_ddr_address_default(u64 phys_addr) +{ + return true; +} + static int rk_minidump_driver_probe(struct platform_device *pdev) { unsigned int i; @@ -689,6 +707,9 @@ static int rk_minidump_driver_probe(struct platform_device *pdev) pr_info("Create /proc/rk_md/minidump fail...\n"); } + if (of_machine_is_compatible("rockchip,rk3588")) + md_is_ddr_address = md_is_ddr_address_rk3588; + /* Check global minidump support initialization */ if (!md_global_toc->md_toc_init) { pr_err("System Minidump TOC not initialized\n"); diff --git a/include/soc/rockchip/rk_minidump.h b/include/soc/rockchip/rk_minidump.h index d025a9a35bbc..c9e9efd2222b 100644 --- a/include/soc/rockchip/rk_minidump.h +++ b/include/soc/rockchip/rk_minidump.h @@ -71,4 +71,5 @@ static inline int rk_minidump_hardlock_notify(struct notifier_block *nb, #endif void rk_md_flush_dcache_area(void *addr, size_t len); +extern bool (*md_is_ddr_address)(u64 virt_addr); #endif /* __RK_MINIDUMP_H */