Files
kernel_common_drivers/drivers/memory_debug/main.c
T
jian.hu 10f2de01c0 iotrace: do nothing if linux,iotrace status is disabled [1/1]
PD#SWPL-181650

Problem:
1.set linux,iotrace status as disabled
BUG: Bad mage state in process insmod  pfn:04f00
page:(ptrval) refcount:1 mapcount:129 mapping:00000000 index:0x0 pfn:0x4f00
anon flags: 0x80014(uptodate|lru|swapbacked|zone=0)
raw: 00080014 00000100 00000122 c1e9c1f9 00000000 00000000 00000080 00000001
page dumped because: PAGE_FLAGS_CHECK_AT_PREP flag(s) set
CPU: 1 PID: 177 Comm: insmod Not tainted 5.15.153-android14-11-00133-gc9b6039dc794 #1
Hardware name: Generic DT based system
[bc0a9928+  12][<c030df1c>] show_stack+0x28/0x2c
[bc0a9958+  44][<c103b9a4>] dump_stack_lvl+0x48/0x54
[bc0a9958+  28][<c0566fec>] bad_page+0x11c/0x120
[bc0a99f8+ 156][<c0567ff8>] get_populated_pcp_list+0xbe4/0xf2c
[bc0a9af0+ 244][<c055fd08>] __rmqueue_pcplist+0x84/0x1270
[bc0a9bc8+ 212][<c05615b0>] get_page_from_freelist+0x268/0x1508
[bc0a9c18+  76][<c0561154>] __alloc_pages+0xf4/0x2e8
[bc0a9c60+  68][<c0558ec8>] __vmalloc_node_range+0x26c/0x420
[bc0a9c98+  52][<c030f090>] module_alloc+0x58/0xac
[bc0a9d10+ 116][<c04083b4>] load_module+0x1388/0x1f54
[bc0a9d98+ 132][<c0405510>] sys_init_module+0x1bc/0x1ec
[0010062a+1141205134][<c0300060>] ret_fast_syscall+0x0/0x48

Solution:
do nothing if linux,iotrace status is disabled in
free_iotrace_reserved_memory

Verify:
t6d br301

Change-Id: I6b5cf5b8ef9b2bce056c2a5d9fd91df9185c73ef
Signed-off-by: jian.hu <jian.hu@amlogic.com>
(cherry picked from commit 398e006c67)
2025-09-17 18:47:11 -07:00

221 lines
4.9 KiB
C

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
//#define DEBUG
#include <linux/module.h>
#include <linux/device.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/kasan.h>
#include <linux/kthread.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/amlogic/module_merge.h>
#include "main.h"
#include <linux/amlogic/aml_free_reserved.h>
#include <linux/amlogic/aml_cma.h>
unsigned long aml_free_reserved_area(void *start, void *end, int poison, const char *s)
{
void *pos;
unsigned long pages = 0;
start = (void *)PAGE_ALIGN((unsigned long)start);
end = (void *)((unsigned long)end & PAGE_MASK);
for (pos = start; pos < end; pos += PAGE_SIZE, pages++) {
struct page *page = virt_to_page(pos);
void *direct_map_addr;
/*
* 'direct_map_addr' might be different from 'pos'
* because some architectures' virt_to_page()
* work with aliases. Getting the direct map
* address ensures that we get a _writeable_
* alias for the memset().
*/
direct_map_addr = page_address(page);
/*
* Perform a kasan-unchecked memset() since this memory
* has not been initialized.
*/
direct_map_addr = kasan_reset_tag(direct_map_addr);
if ((unsigned int)poison <= 0xFF)
memset(direct_map_addr, poison, PAGE_SIZE);
free_reserved_page(page);
}
if (pages && s)
pr_info("Freeing %s memory: %ldK\n",
s, pages << (PAGE_SHIFT - 10));
return pages;
}
EXPORT_SYMBOL(aml_free_reserved_area);
#if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE)
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/amlogic/aml_iotrace.h>
#if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTM)
#include <linux/amlogic/aml_iotm.h>
#endif
void free_iotrace_reserved_memory(void)
{
int ret;
struct resource res;
struct device_node *node = NULL;
node = of_find_node_by_path("/reserved-memory/linux,iotrace");
if (!node)
return;
/* Do nothing if linux,iotrace status is disabled */
if (!of_device_is_available(node))
return;
ret = of_address_to_resource(node, 0, &res);
if (ret)
return;
// free reserved-memory if no need
if (!ramoops_ftrace_en) {
#if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTM)
unsigned int iotm_ddr_size = 0;
/* exclude iotm_ddr_size in axi_mode. */
if (iotm_en_ddr_size_get(&iotm_ddr_size) && iotm_monitor_mode_get() == 0)
res.end = res.end - PAGE_ALIGN(iotm_ddr_size);
#endif
aml_free_reserved_area(__va(res.start), __va(PAGE_ALIGN(res.end)), 0,
"free_reserved");
pr_debug("free iotrace reserved_memory\n");
}
}
#endif
#define MAX_CMA_TASKS 8
struct task_struct *matched_cmatasks[MAX_CMA_TASKS];
static int get_current_cma_task_nice(void)
{
if (matched_cmatasks[0])
return task_nice(matched_cmatasks[0]);
pr_err("can not find cma task thread.\n");
return -EINVAL;
}
static int set_cma_task_nice(int nice)
{
int cur_nice;
int i = 0;
cur_nice = get_current_cma_task_nice();
if (cur_nice == -EINVAL || cur_nice == nice)
return 0;
for (i = 0; i < MAX_CMA_TASKS; i++) {
if (matched_cmatasks[i])
set_user_nice(matched_cmatasks[i], nice);
}
pr_info("renice cma task to %d\n", nice);
return 0;
}
/*
* level 0: nice = -17, default value
* level 1: nice = -10
* level 2: nice = 0
*/
int set_cma_task_priority_level(int level)
{
int ret;
int cma_task_level[] = {-17, -10, 0};
if (level < 0 || level > 2) {
pr_err("out of level range: [0-2]");
return -EINVAL;
}
ret = set_cma_task_nice(cma_task_level[level]);
return ret;
}
EXPORT_SYMBOL(set_cma_task_priority_level);
static int find_cma_task_hook(void *data)
{
struct task_struct *tsk;
int i = 0;
char task_name[MAX_CMA_TASKS][20] = {0};
for (i = 0; i < MAX_CMA_TASKS; i++)
sprintf(task_name[i], "cma_task%d", i);
while (1) {
rcu_read_lock();
for_each_process(tsk) {
/* skip userspace task */
if (tsk->mm)
continue;
for (i = 0; i < MAX_CMA_TASKS; i++) {
if (matched_cmatasks[i])
continue;
if (!strncmp(tsk->comm, task_name[i], 9)) {
matched_cmatasks[i] = tsk;
break;
}
}
}
rcu_read_unlock();
if (matched_cmatasks[0])
break;
msleep_interruptible(500);
}
return 0;
}
static int __init memory_main_init(void)
{
pr_debug("### %s() start\n", __func__);
call_sub_init(filecache_module_init);
call_sub_init(aml_watch_pint_init);
call_sub_init(aml_reg_init);
call_sub_init(ddr_tool_init);
call_sub_init(ramdump_init);
#if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE)
free_iotrace_reserved_memory();
#endif
pr_debug("### %s() end\n", __func__);
kthread_run(find_cma_task_hook, NULL, "find_cma_task");
return 0;
}
static void __exit memory_main_exit(void)
{
ramdump_uninit();
ddr_tool_exit();
aml_reg_exit();
aml_watch_point_uninit();
filecache_module_exit();
}
module_init(memory_main_init);
module_exit(memory_main_exit);
MODULE_LICENSE("GPL v2");