huawei-mrd-kernel/drivers/rphone/rsharedmemcheck/shared_mem_check_basic.c

192 lines
5.3 KiB
C
Raw Permalink Normal View History

/* this file need not to be modified when new memmory free func is added to the injection list*/
#include "shared_memory_check.h"
char single_filler_page[PAGE_SIZE];
char filler_pages_with_order_4[PAGE_SIZE * (1 << 4)];
char filler_pages_with_order_8[PAGE_SIZE * (1 << 8)];
DEFINE_SPINLOCK(sm_list_lock);
int total_delay_size[CUR_SM_DELAY_TYPE_NR] ={
0, //current delay memeory size for ION SYSTEM HEAP
0, //current delay memory size for remap pfn range
};
int total_num = 0;
struct transaction_node head = {
.probe_type = -1,
};
struct timer_list* main_timer;
void remark_shared_memory_page(struct page* page) {
if (page == NULL) {
printk("[SharedMemCheck]remark shared memory page fail because of null pointer.\n");
return;
}
page->flags |= HIT_MASK;
return;
}
int is_shared_memory_page(struct page* page) {
if (page == NULL) {
printk("[SharedMemCheck]check flag of shared memory page fail because of null pointer.\n");
return false;
} else {
return (page->flags & HIT_MASK) == HIT_MASK;
}
}
void clear_shared_memory_remark(struct page* page) {
if (page == NULL) {
printk("[SharedMemCheck]check flag of shared memory page fail because of null pointer.\n");
return;
} else {
page->flags = page->flags & (~HIT_MASK);
}
}
//memory check func that check each byte.
int memory_check_base_on_byte(char* buffer, int size) {
int i;
for(i = 0; i < size; i++) {
if(likely(buffer[i] == FILLER)) {
continue;
} else {
return -1;
}
}
return 0;
}
//memory check func that check each page
int memory_check_base_on_page(char *buffer, int size, int order) {
int i;
int step = PAGE_SIZE;
char* filler_buffer = single_filler_page;
if (order >= 4 && order < 8) {
step = PAGE_SIZE * (1<<4);
filler_buffer = filler_pages_with_order_4;
} else if(order >= 8) {
step = PAGE_SIZE * (1<<8);
filler_buffer = filler_pages_with_order_8;
}
for(i = 0; i < size; i += step) {
if(likely(memcmp(filler_buffer, buffer + i, step)) == 0) {
continue;
} else {
return -1;
}
}
return 0;
}
/***************************************************************************************
definition of fault injection.Normally two types of func should be injected:
1. function that we find and remark shared memory by setting flag.
2. function that shared memory is being freed.Delay it.
**************************************************************************************/
rasprobe_entry_define(ion_page_pool_free_immediate);
rasprobe_entry_define(__free_pages);
rasprobe_entry_define(remap_pfn_range);
static struct rasprobe *probes[] = {
&rasprobe_name(ion_page_pool_free_immediate),
&rasprobe_name(__free_pages),
&rasprobe_name(remap_pfn_range),
};
//check the delayed memmory list
void check_my_list(void* args) {
struct transaction_node *node, *next;
if(list_empty(&(head.list))) {
printk("list empty.\n");
}
list_for_each_entry_safe(node, next, &(head.list), list) {
if(jiffies - node->expires >= 2*HZ) {
switch(node->probe_type) {
default:
//printk("[call timer in check list]node addr:%lx probe_type:%d para0:%lx para1 addr:%lx, para1 value:%d\n", (unsigned long)node, node->probe_type, (unsigned long)(node->para0), (unsigned long)(node->para1), *((int *)(node->para1)));
spin_lock(&sm_list_lock);
list_del(&(node->list));
total_delay_size[node->probe_type] -= 4096 << (*((int *)(node->para1)));
total_num--;
spin_unlock(&sm_list_lock);
node->function(node);
kfree(node->para1);
kfree(node);
break;
}
} else {
break;
}
}
mod_timer(main_timer, jiffies + HZ);
return;
}
static int tool_init(void)
{
INIT_LIST_HEAD(&(head.list));
/*3. initialize probes and interface*/
total_num = 0;
memset(single_filler_page, FILLER, PAGE_SIZE);
memset(filler_pages_with_order_4, FILLER, PAGE_SIZE * (1 << 4));
memset(filler_pages_with_order_8, FILLER, PAGE_SIZE * (1 << 8));
rasprobe_name(ion_page_pool_free_immediate).maxactive = 4;
printk("[memcheck init]total_delay_size[ION SYS]:%d, total_delay_size[REMAP_PAGES]:%d, total_num:%d\n", total_delay_size[0], total_delay_size[1], total_num);
ras_retn_iferr(register_rasprobes(probes, ARRAY_SIZE(probes)));
main_timer = (struct timer_list *)kmalloc(sizeof(struct timer_list), GFP_KERNEL);
init_timer(main_timer);
main_timer->expires = jiffies + 2*HZ;
main_timer->function = check_my_list;
main_timer->data = 0;
add_timer(main_timer);
return 0;
}
static void clear_before_module_exit(void) {
struct transaction_node* node, *next;
printk("[memcheck exit]memcheck exit\n");
del_timer(main_timer);
list_for_each_entry_safe(node, next, &(head.list), list) {
switch(node->probe_type) {
case MEM_ION_SYSTEM_HEAP:
case MEM_REMAP_PAGES:
printk("timer func: free_pages probe_type:%d para0:%lx para1 addr:%lx, para1 value:%d\n", node->probe_type, (unsigned long)node->para0, (unsigned long)node->para1, *((int *)(node->para1)));
list_del(&(node->list));
node->function(node);
kfree((unsigned int *)(node->para1));
kfree(node);
break;
default: break;
}
}
}
static void tool_exit(void)
{
unregister_rasprobes(probes, ARRAY_SIZE(probes));
clear_before_module_exit();
}
module_init(tool_init);
module_exit(tool_exit);
MODULE_DESCRIPTION("Delayed memory free test.");
MODULE_LICENSE("GPL");
MODULE_VERSION("V001R001C151-1.0");