kernel_samsung_a34x-permissive/drivers/misc/mediatek/aee/mrdump/mrdump_control.c

137 lines
3.9 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2016 MediaTek Inc.
*/
#include <linux/bug.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <asm/memory.h>
#include <asm/sections.h>
#include <mt-plat/mrdump.h>
#include "mrdump_private.h"
struct mrdump_control_block *mrdump_cblock;
#if defined(CONFIG_KALLSYMS) && !defined(CONFIG_KALLSYMS_BASE_RELATIVE)
static void mrdump_cblock_kallsyms_init(struct mrdump_ksyms_param *kparam)
{
unsigned long start_addr = (unsigned long) &kallsyms_addresses;
kparam->tag[0] = 'K';
kparam->tag[1] = 'S';
kparam->tag[2] = 'Y';
kparam->tag[3] = 'M';
switch (sizeof(unsigned long)) {
case 4:
kparam->flag = KSYM_32;
break;
case 8:
kparam->flag = KSYM_64;
break;
default:
BUILD_BUG();
}
kparam->start_addr = __pa_symbol(start_addr);
kparam->size = (unsigned long)&kallsyms_token_index - start_addr + 512;
kparam->crc = crc32(0, (unsigned char *)start_addr, kparam->size);
kparam->addresses_off = (unsigned long)&kallsyms_addresses - start_addr;
kparam->num_syms_off = (unsigned long)&kallsyms_num_syms - start_addr;
kparam->names_off = (unsigned long)&kallsyms_names - start_addr;
kparam->markers_off = (unsigned long)&kallsyms_markers - start_addr;
kparam->token_table_off =
(unsigned long)&kallsyms_token_table - start_addr;
kparam->token_index_off =
(unsigned long)&kallsyms_token_index - start_addr;
}
#else
static void mrdump_cblock_kallsyms_init(struct mrdump_ksyms_param *unused)
{
}
#endif
__init void mrdump_cblock_init(phys_addr_t cb_addr, phys_addr_t cb_size)
{
struct mrdump_machdesc *machdesc_p;
if (cb_addr == 0) {
pr_notice("%s: mrdump control address cannot be 0\n",
__func__);
return;
}
if (cb_size < sizeof(struct mrdump_control_block)) {
pr_notice("%s: not enough space for mrdump control block\n",
__func__);
return;
}
mrdump_cblock = ioremap_wc(cb_addr, cb_size);
if (!mrdump_cblock) {
pr_notice("%s: mrdump_cb not mapped\n", __func__);
return;
}
memset_io(mrdump_cblock, 0, sizeof(struct mrdump_control_block));
memcpy_toio(mrdump_cblock->sig, MRDUMP_GO_DUMP,
sizeof(mrdump_cblock->sig));
machdesc_p = &mrdump_cblock->machdesc;
machdesc_p->nr_cpus = nr_cpu_ids;
machdesc_p->page_offset = (uint64_t)PAGE_OFFSET;
machdesc_p->high_memory = (uintptr_t)high_memory;
#if defined(KIMAGE_VADDR)
machdesc_p->kimage_vaddr = KIMAGE_VADDR;
#endif
#if defined(TEXT_OFFSET)
machdesc_p->kimage_vaddr += TEXT_OFFSET;
#endif
machdesc_p->dram_start = (uint64_t)aee_memblock_start_of_DRAM();
machdesc_p->dram_end = (uint64_t)aee_memblock_end_of_DRAM();
machdesc_p->kimage_stext = (uint64_t)aee_get_text();
machdesc_p->kimage_etext = (uint64_t)aee_get_etext();
machdesc_p->kimage_stext_real = (uint64_t)aee_get_stext();
#if defined(CONFIG_ARM64)
machdesc_p->kimage_voffset = kimage_voffset;
#endif
machdesc_p->vmalloc_start = (uint64_t)VMALLOC_START;
machdesc_p->vmalloc_end = (uint64_t)VMALLOC_END;
machdesc_p->modules_start = (uint64_t)MODULES_VADDR;
machdesc_p->modules_end = (uint64_t)MODULES_END;
machdesc_p->phys_offset = (uint64_t)(phys_addr_t)PHYS_OFFSET;
if (virt_addr_valid(aee_get_swapper_pg_dir())) {
machdesc_p->master_page_table =
(uintptr_t)__pa(aee_get_swapper_pg_dir());
} else {
machdesc_p->master_page_table =
(uintptr_t)__pa_symbol(aee_get_swapper_pg_dir());
}
#if defined(CONFIG_SPARSEMEM_VMEMMAP)
machdesc_p->memmap = (uintptr_t)vmemmap;
#endif
machdesc_p->pageflags = (1UL << PG_uptodate) + (1UL << PG_dirty) +
(1UL << PG_lru) + (1UL << PG_writeback);
machdesc_p->struct_page_size = (uint32_t)sizeof(struct page);
mrdump_cblock_kallsyms_init(&machdesc_p->kallsyms);
mrdump_cblock->machdesc_crc = crc32(0, machdesc_p,
sizeof(struct mrdump_machdesc));
pr_notice("%s: done.\n", __func__);
/* TODO: remove flush APIs after full ramdump support HW_Reboot*/
aee__flush_dcache_area(mrdump_cblock,
sizeof(struct mrdump_control_block));
}