[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/os/linux/linux-3.4.x/mm/mem_tracker.c b/ap/os/linux/linux-3.4.x/mm/mem_tracker.c
new file mode 100755
index 0000000..3963763
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/mm/mem_tracker.c
@@ -0,0 +1,407 @@
+/*
+ *  linux/mm/mem_tracker.c
+ *
+ *  Copyright (C) 1993  Linus Torvalds
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *   vmalloc/vfree, Tigran Aivazian <tigran@veritas.com>, May 2000
+ *  Major rework to support vmap/vunmap, Christoph Hellwig, SGI, August 2002
+ *  Numa awareness, Christoph Lameter, SGI, June 2005
+ */
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/list.h>
+#include <linux/pfn.h>
+#include <linux/atomic.h>
+#include <asm/stacktrace.h>
+#include <mach/iomap.h>
+#include <linux/kprobes.h>
+#include <asm/traps.h>
+#include <linux/mem_tracker_def.h>
+
+/*******************************************************************************
+*                                   ºê¶¨Òå                                     *
+*******************************************************************************/
+#ifdef CONFIG_KALLSYMS
+#define MEM_TRACKER_MAX_STACK_LEN  	(100)  /*Õ»º¯Êý¹ì¼£µÄ×Ö·û¸öÊýÉÏÏÞ£»*/
+#endif 
+#define MEM_TRACKER_MAX_STACK_LEVEL (6)    /*Õ»µÄ²ãÊý*/
+#define MEM_TRACKER_NOT_TRACE_LEVEL (2)
+#define MEM_TRACKER_ALLOCED         0x00
+#define MEM_TRACKER_FREED          	0x02
+
+/*******************************************************************************
+*                                Êý¾ÝÀàÐͶ¨Òå                                  *
+*******************************************************************************/
+struct heap_record {
+    struct list_head    node;
+	void	 			*addr;    /*ÉêÇë³öµÄÄÚ´æµØÖ·*/
+	unsigned int        employ:8;
+    unsigned int 		size:24;	  /*¼Ç¼ÉêÇëµÄÄڴ泤¶È*/
+	char                task_name[TASK_COMM_LEN];
+#ifdef CONFIG_KALLSYMS
+    char				stack_frame[MEM_TRACKER_MAX_STACK_LEVEL][MEM_TRACKER_MAX_STACK_LEN];
+								/*º¯Êý»ØËݹ켣*/
+#else
+	unsigned long 	    stack_frame[MEM_TRACKER_MAX_STACK_LEVEL];
+#endif
+};
+
+/*******************************************************************************
+*                                º¯ÊýÉùÃ÷                                  *
+*******************************************************************************/
+/*******************************************************************************
+*								 È«¾Ö±äÁ¿¶¨Òå								   *
+*******************************************************************************/
+int 				kmem_node_max;
+int 				node_list_max;     
+static spinlock_t  	buddy_track_lock;
+static spinlock_t  	kmem_track_lock;
+
+
+/*ÕýÔÚʹÓõÄÊý¾ÝÁ´±í*/
+static LIST_HEAD(buddy_employ_head);
+static LIST_HEAD(kmem_employ_head);
+
+/*ÒѾ­ÊͷŵÄÊý¾ÝÁ´±í*/
+static LIST_HEAD(buddy_free_head);
+static LIST_HEAD(kmem_free_head);
+
+/*******************************************************************************
+*                                ¾Ö²¿º¯ÊýʵÏÖ                                  *
+*******************************************************************************/
+static void memset_tracker(struct heap_record * node)
+{
+	node->size = 0;
+	node->addr = NULL;
+	
+	memset(node->task_name,0, TASK_COMM_LEN);
+	memset(node->stack_frame, 0, sizeof(node->stack_frame));
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: 	¶Ôµ±Ç°Õ»½øÐлØËÝ£¬½«º¯Êý¹ì¼£±£´æ
+* ²ÎÊý˵Ã÷: 	
+*	(´«Èë²ÎÊý)	my_frame:¹ì¼£ÐÅÏ¢±£´æµÄµØÖ·
+*               
+*	(´«³ö²ÎÊý)	void
+* ·µ »Ø Öµ: 	void
+* ÆäËü˵Ã÷: 	ÎÞ
+*******************************************************************************/
+#ifdef CONFIG_KALLSYMS
+void get_stack_process(unsigned char *my_frame)
+#else
+void get_stack_process(unsigned long *my_frame)
+#endif 
+{
+	int urc;
+	int i 	= 0;
+#ifdef CONFIG_KALLSYMS
+	char mytmp[MEM_TRACKER_MAX_STACK_LEN] = {0};
+#endif
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+#ifndef CONFIG_KALLSYMS
+    memset(my_frame, 0, MEM_TRACKER_MAX_STACK_LEVEL * sizeof(unsigned long));
+#endif
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.lr = (unsigned long)__builtin_return_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)get_stack_process;
+
+	while (1) {		
+		urc = unwind_frame(&frame);
+		/*Èô»ØËݽáÊø£¬ÔòÁ¢¼´Í˳ö*/
+		if (urc < 0)
+		    return;
+
+		/*ΪÁ˽ÚÊ¡Äڴ棬×îÉϲãµÄ2¸öº¯Êý²»¸ú×Ù*/
+		if (++i >= MEM_TRACKER_NOT_TRACE_LEVEL) {
+#ifdef CONFIG_KALLSYMS
+			snprintf(mytmp, MEM_TRACKER_MAX_STACK_LEN - 1, "<%ps>", (void *)frame.pc);
+			strcpy(my_frame + ((i - MEM_TRACKER_NOT_TRACE_LEVEL) * MEM_TRACKER_MAX_STACK_LEN), mytmp);
+#else
+			my_frame[i - MEM_TRACKER_NOT_TRACE_LEVEL] = (unsigned long)frame.pc;
+#endif	
+			if (i - MEM_TRACKER_NOT_TRACE_LEVEL >= MEM_TRACKER_MAX_STACK_LEVEL - 1)
+				return;
+		}
+	}
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: 	»ñÈ¡×îºóÒ»¸ö½Úµã
+* ²ÎÊý˵Ã÷: 	
+*	(´«Èë²ÎÊý)	head:Á´±íÍ·
+*	(´«³ö²ÎÊý)	track¸ú×ÙÐÅÏ¢
+* ·µ »Ø Öµ: 	void
+* ÆäËü˵Ã÷: 	ÎÞ
+*******************************************************************************/
+static struct list_head *list_get_last_node(struct list_head *head)
+{
+ 	struct heap_record 	*h 		   = NULL;
+	struct list_head 	*tail_node = NULL;
+	
+ 	if (list_empty(head))
+		return NULL;
+
+    tail_node = head->prev;
+	
+	h = container_of(tail_node, struct heap_record, node);
+	
+    if(h->employ == MEM_TRACKER_FREED)
+		list_del(head->prev);		
+	else
+		panic("[MEM_TRACKER]list error");
+	
+	return tail_node;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö:     ÄÚ´æ¸ú×Ù³õʼ»¯
+* ²ÎÊý˵Ã÷:     
+*   (´«Èë²ÎÊý)  void             
+*   (´«³ö²ÎÊý)  void
+* ·µ »Ø Öµ:     void
+* ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ 
+*******************************************************************************/
+void mem_trace_init(void)
+{
+    int 				index;
+	unsigned long 		flags;
+    struct heap_record *record = NULL;
+	void __iomem 		*base  = NULL;
+	
+    spin_lock_init(&buddy_track_lock);
+	
+    spin_lock_irqsave(&buddy_track_lock, flags);
+	
+	base 			= ZX_MEM_TRACKER_BASE; 
+	node_list_max 	= ZX_MEM_TRACKER_SIZE / sizeof(struct heap_record);
+
+	/* ³õʼ»¯¿ÕÏÐÄÚ´æ½ÚµãÁ´±í */
+    for (index = 0; index < node_list_max; index++)
+    {
+        record = (struct heap_record *)(base + index * sizeof(struct heap_record));
+		record->employ = MEM_TRACKER_FREED;
+		list_add(&record->node, &buddy_free_head);
+    }
+	
+    spin_unlock_irqrestore(&buddy_track_lock, flags);
+}
+
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö:     kmallocÄÚ´æ¸ú×Ù³õʼ»¯
+* ²ÎÊý˵Ã÷:     
+*   (´«Èë²ÎÊý)  void             
+*   (´«³ö²ÎÊý)  void
+* ·µ »Ø Öµ:     void
+* ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ 
+*******************************************************************************/
+void kmalloc_trace_init(void)
+{
+    int 				index;
+	unsigned long 		flags;
+    struct heap_record *record = NULL;
+	void __iomem 		*base  = NULL;
+	
+	spin_lock_init(&kmem_track_lock);
+	spin_lock_irqsave(&kmem_track_lock, flags);
+
+	base 			= ZX_KMALLOC_TRACKER_BASE; 
+	kmem_node_max 	= ZX_KMALLOC_TRACKER_SIZE / sizeof(struct heap_record);
+
+	/* ³õʼ»¯¿ÕÏÐÄÚ´æ½ÚµãÁ´±í */
+    for (index = 0; index < kmem_node_max; index++)
+    {
+        record = (struct heap_record *)(base + index * sizeof(struct heap_record));
+		record->employ = MEM_TRACKER_FREED;
+		list_add(&record->node, &kmem_free_head);
+    }
+
+    spin_unlock_irqrestore(&kmem_track_lock, flags);
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö:     ÑéÖ¤entry½ÚµãºÏ·¨ÐÔ
+* ²ÎÊý˵Ã÷:     
+*   (´«Èë²ÎÊý)  void             
+*   (´«³ö²ÎÊý)  void
+* ·µ »Ø Öµ:     void
+* ÆäËü˵Ã÷:    ΪʵÏÖÄÚ´æ¹ì¼£¸ú×Ùʱ²»Õ¼ÓÃÏÖÓÐÄڴ棬ʹÓÃ64MÒÔºóµÄÄÚ´æ 
+*******************************************************************************/
+int check_node_entry(const int entry)
+{
+	void __iomem *base	= NULL;
+	long		 limit  = 0;	 
+	
+	base  = ZX_KMALLOC_TRACKER_BASE; 
+	limit = ZX_KMALLOC_TRACKER_SIZE + (int)base;
+	
+	if ((entry >= base) && (entry < limit))
+		return MEM_TRUE;
+	
+	return MEM_FALSE;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: 	ÉêÇëÄÚ´æµãµ÷Óøýӿڣ¬¼Ç¼ÄÚ´æÉêÇë¹ì¼£
+* ²ÎÊý˵Ã÷: 	
+*	(´«Èë²ÎÊý)	addr:ÄÚ´æµØÖ·
+*               order:Äڴ泤¶È,orderΪµ¥Î»£¬2µÄorder´Î·½¸öÒ³
+*	(´«³ö²ÎÊý)	void
+* ·µ »Ø Öµ: 	void
+* ÆäËü˵Ã÷: 	ÎÞ
+*******************************************************************************/
+void mem_alloc_tracker(void *addr, int order)
+{
+    unsigned long 		spin_flag;
+    struct heap_record  *section    = NULL;
+	struct list_head 	*head_ptr  = NULL; 
+	struct page 		*page_addr = NULL;
+
+	if(!addr)
+		panic("[MEM_TRACKER] input item error\n");
+
+	page_addr = (struct page *)(addr);
+   	
+    spin_lock_irqsave(&buddy_track_lock, spin_flag);
+    if (!(head_ptr = list_get_last_node(&buddy_free_head)))
+    {
+		printk("[MEM_TRACKER]buddy free_link_node have no node!!!\n");
+		spin_unlock_irqrestore(&buddy_track_lock, spin_flag);
+		return;
+    }
+    spin_unlock_irqrestore(&buddy_track_lock, spin_flag);
+	section = container_of(head_ptr, struct heap_record, node);
+
+	/*³õʼ»¯½ÚµãÐÅÏ¢*/
+    memset_tracker(section);
+	section->addr 	= addr;
+	section->size 	= (1 << order) * PAGE_SIZE;
+	section->employ = MEM_TRACKER_ALLOCED;
+	memcpy(section->task_name, current->comm, TASK_COMM_LEN);	
+
+	/*»ñȡջ¹ì¼£*/
+	get_stack_process(section->stack_frame);
+	page_addr->mem_track_entry = section;
+	
+	/*¼ÓÈëÒÑÉêÇëÄÚ´æ½Úµã¼Ç¼Á´±í*/
+    spin_lock_irqsave(&buddy_track_lock, spin_flag);
+    list_add(&section->node, &buddy_employ_head);
+    spin_unlock_irqrestore(&buddy_track_lock,spin_flag);
+}
+EXPORT_SYMBOL(mem_alloc_tracker);
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: 	kmallocÉêÇëÄÚ´æµãµ÷Óøýӿڣ¬¼Ç¼ÄÚ´æÉêÇë¹ì¼£
+* ²ÎÊý˵Ã÷: 	
+*	(´«Èë²ÎÊý)	addr:ÄÚ´æµØÖ·
+*               len:Äڴ泤¶È
+*	(´«³ö²ÎÊý)	void
+* ·µ »Ø Öµ: 	void
+* ÆäËü˵Ã÷: 	ÎÞ
+*******************************************************************************/
+void kmalloc_alloc_tracker(void *addr, int len)
+{
+    unsigned long 		spin_flag;
+    struct heap_record *section   		  = NULL;
+	struct list_head 	*head_ptr 	      = NULL;
+	struct list_head 	*free_node_head   = NULL;                                         
+	struct list_head 	*employ_node_head = NULL;  
+	struct page 		*page_addr 	      = NULL;
+
+	if(!addr)
+		panic("[MEM_TRACKER] input item error\n");
+
+	free_node_head   = &kmem_free_head;
+	employ_node_head = &kmem_employ_head;
+	
+    spin_lock_irqsave(&kmem_track_lock, spin_flag);
+    
+    if (!(head_ptr = list_get_last_node(free_node_head)))
+    {
+		printk("[MEM_TRACKER]kmalloc free_link_node have no node!!!\n");
+		spin_unlock_irqrestore(&kmem_track_lock, spin_flag);
+		return;
+    }
+    spin_unlock_irqrestore(&kmem_track_lock, spin_flag);
+
+	section = container_of(head_ptr, struct heap_record, node);
+
+	/*³õʼ»¯½ÚµãÐÅÏ¢*/
+    memset_tracker(section);
+	section->addr 	= KMALLOC_SETUP(addr);
+	section->size 	= len;
+	section->employ = MEM_TRACKER_ALLOCED;
+	memcpy(section->task_name, current->comm, TASK_COMM_LEN);	
+
+	/*»ñȡջ¹ì¼£*/
+	get_stack_process(section->stack_frame);
+	KMALLOC_SET_ENTRY(addr, section);
+
+	if(MEM_FALSE == check_node_entry(section))
+		panic("error");
+ 
+	/*¼ÓÈëÒÑÉêÇëÄÚ´æ½Úµã¼Ç¼Á´±í*/
+    spin_lock_irqsave(&kmem_track_lock, spin_flag);
+    list_add(&section->node, employ_node_head);
+	
+    spin_unlock_irqrestore(&kmem_track_lock,spin_flag);
+}
+EXPORT_SYMBOL(kmalloc_alloc_tracker);
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: 	ÊÍ·ÅÄÚ´æµãµ÷ÓøýӿÚ
+* ²ÎÊý˵Ã÷: 	
+*	(´«Èë²ÎÊý)	entry:ÄÚ´æµØÖ·        
+*	(´«³ö²ÎÊý)	void
+* ·µ »Ø Öµ: 	void
+* ÆäËü˵Ã÷: 	ÎÞ
+*******************************************************************************/
+void mem_free_tracker(void *entry, int type)
+{
+    unsigned long 	   spin_flag;
+	spinlock_t 		   *mem_lock       = NULL;
+	struct list_head   *free_node_head = NULL;     
+    struct heap_record *free_node = (struct heap_record *)entry;
+
+    if (entry == NULL)
+		return;
+
+	if (type == MEM_TRACKER_TYPE_BUDDY)
+	{
+		mem_lock = &buddy_track_lock;
+		free_node_head = &buddy_free_head;
+	}
+	else if (type == MEM_TRACKER_TYPE_KMALLOC)
+	{
+		mem_lock = &kmem_track_lock;
+		free_node_head = &kmem_free_head;
+	}
+	else
+		panic("mem_tracker type error\n");
+
+    spin_lock_irqsave(mem_lock, spin_flag);
+
+	if (free_node->employ == MEM_TRACKER_ALLOCED)
+	{
+		free_node->employ = MEM_TRACKER_FREED;	
+		list_move(&free_node->node, free_node_head);
+	}
+	else 
+	{		    
+		printk("[MEM_TRACKER]error: employ is 0x%x  employ_node MEM_TRACKER_FREED !!\n", free_node->employ);
+	}
+	
+	spin_unlock_irqrestore(mem_lock, spin_flag);		  
+}
+EXPORT_SYMBOL(mem_free_tracker);
+
+
+