From 363a42e425aa807a516b3881fce094fdcaaa5f88 Mon Sep 17 00:00:00 2001 From: hsl Date: Thu, 27 Jan 2011 16:17:35 +0800 Subject: [PATCH] HSL: dbg:add some debug function --- arch/arm/kernel/entry-common.S | 3 +- drivers/Makefile | 2 + drivers/dbg/Makefile | 7 + drivers/dbg/debug.c | 690 +++++++++++++++++++++++++++++++++ drivers/dbg/kobj.c | 100 +++++ drivers/dbg/wrapcall.S | 94 +++++ 6 files changed, 895 insertions(+), 1 deletion(-) create mode 100644 drivers/dbg/Makefile create mode 100644 drivers/dbg/debug.c create mode 100644 drivers/dbg/kobj.c create mode 100644 drivers/dbg/wrapcall.S diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index a6c66f598d14..8e7ad911b579 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -22,7 +22,8 @@ * possible here, and this includes saving r0 back into the SVC * stack. */ -ret_fast_syscall: +/* ret_fast_syscall: */ +ENTRY(ret_fast_syscall) UNWIND(.fnstart ) UNWIND(.cantunwind ) disable_irq @ disable interrupts diff --git a/drivers/Makefile b/drivers/Makefile index 68548675116c..972651f36381 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -115,3 +115,5 @@ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ obj-y += ieee802154/ obj-$(CONFIG_CMMB) += cmmb/ +obj-y += dbg/ + diff --git a/drivers/dbg/Makefile b/drivers/dbg/Makefile new file mode 100644 index 000000000000..9d25852fd1b8 --- /dev/null +++ b/drivers/dbg/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for rk_scu drivers. +# +obj-y :=wrapcall.o debug.o kobj.o + + + diff --git a/drivers/dbg/debug.c b/drivers/dbg/debug.c new file mode 100644 index 000000000000..91f05c4dc9ee --- /dev/null +++ b/drivers/dbg/debug.c @@ -0,0 +1,690 @@ +/* + * function for test and debug + * + * Copyright (C) 2011 Rochchip, Inc. + * Author: Hsl + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * relative files: drivers/dbg/ , arch/arm/kernel/entry-common.S + * LOG: + * 20110127, HSL@RK,add get user regs support and kernel io support. + */ + +/* #define DEBUG */ +#include +#include +#include + + +/* + * 20090725,hsl,some debug function start from here + */ +#include +#include +#include +#include + +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define FIND_TASK_BY_PID(x) find_task_by_vpid(x) +#else +#define FIND_TASK_BY_PID(x) find_task_by_pid(x) +#endif + +extern int __scu_call_wrap(unsigned long *argv , int argc , int fun ); +extern void ret_fast_syscall( void ); + +void rk28_printk_mem( unsigned int * addr , int words , unsigned int* show_addr ) +{ + unsigned int * reg_base = addr ; + if( show_addr == NULL ){ + show_addr = addr; + } + while( words > 0 ) { + printk("%p:%08x %08x %08x %08x\n" ,show_addr , + reg_base[0],reg_base[1],reg_base[2],reg_base[3]); + words -= 4; + reg_base += 4; + show_addr += 4; + } +} + +/* + * type define : + * first for function name , + * ',' for argument. + * \' : char + * \" : string. + * other : for int,short,0x for hex.0 for octal. + * 20090811,for easy use , 0x or 0-9 start means num , other ,means string . + * len = 1 string for char. + * 20100420,add nagative support. + */ +int dbg_get_arg( char ** pp ) +{ + char * p = *pp; + char *t; + int ret; + int len ; + int nag = 0; + int bnum = 0; + if( p[0] == '-' ) { + nag = 1; + p++; + } + if( p[0] == '0' ) { + if( ( p[1] == 'x' || p[1] == 'X' ) ) { + p+= 2; + len = sscanf(p,"%x" , &ret ); + p += len; + } else { + if( p[1] == 0 || p[1] == ',' ) { + ret = 0; /* only one '0' , must be zero */ + p++; + } else { + p+= 1; + len = sscanf(p,"%o" , &ret ); + p += len; + } + } + bnum = 1; + } else if( p[0] >= '1' && p[0] <= '9' ) { + len = sscanf(p,"%d" , (int*)&ret ); + p += len; + bnum = 1; + } else if( p[0] == '\'' ) { + ret = p[1]; + p++; + } else { /* all for string */ + if ( p[0] == '\"' ) { + if( p[1] == '\"' ) { /* NULL string */ + ret = 0; + p+=2; + } else { + ret = (unsigned long)(p+1); + t = strchr( p+1 , '\"' ); + if( t ) { + *t = 0; + p = t+1 ; + } else { + p++; + } + } + } else { + if( *p == ',' ) {/* empty ,as NULL string */ + ret = 0; + p--; + } else if( *p == ' ' || *p == 0 ) /* one char string ,as char.*/ + ret = *p; + else /* as string */ + ret = (unsigned long)(p); + p++; + } + } + t = strchr( p , ',' ); + if( t ) { + *t = 0; + *pp = t+1; + } else { /* p should be the last one */ + while(*p != ' ' && *p != 0 && *p != '\n' ) + p++; + *p = 0; + *pp = p; + } + if( nag && bnum ) + ret = 0-ret; + return ret; +} +int dbg_parse_cmd( char * cdb ) +{ + unsigned long reg[6]; + unsigned long fun; + int argc = 0 ; + char *p = cdb ; + char *sym = p; + int ret; + + //SCU_BUG("CMD=%s\n" , cdb); + memset( reg , 0 , sizeof reg ); + p = strchr(p , ','); + if( p ) { + *p++ = 0; + while( *p && argc < 6) { + reg[argc++] = (unsigned long)dbg_get_arg( &p ); + } + } + //debug_print("sym=%s,argc=%d,db=%s\n" , sym ,argc , cdb ); + if( sym[0] == '0' && ( sym[1] == 'x' || sym[1] == 'X' ) ) { + fun = 0; + sscanf(sym+2,"%lx" , &fun ); + } else { + fun = kallsyms_lookup_name(sym); + //debug_print("after lookup symbols,sym=%s,fun=0x%p\n" , sym ,fun); + } + + /* 20100409,HSL@RK,use printk to print to buffer. + */ + printk("@CALL@ %s(0x%p),argc=%d\n" , sym , (void*)fun , argc); + if( fun ) { + ret = __scu_call_wrap( reg,argc,fun); + } else { + ret = -EIO; + } + /* 20100722,"@return" for function print end tag. + */ + printk("@return 0x%x(%d)\n" , ret , ret); + return ret; +} + +#if 0 +/** + * check arg be a string or int or symbol addr . + * 1: string , 2: kernel sym , 0:other + */ +int rk28_arg_string( unsigned long arg ) +{ + if( arg > (unsigned long)&_end && arg < 0xc8000000 ) + return 1; + if( arg >= (unsigned long)&_text && arg < (unsigned long)&_end ) + return 2; + return 0; +} +#endif + +static struct pt_regs * unwind_get_regs(struct task_struct *tsk) +{ + struct stackframe frame; + register unsigned long current_sp asm ("sp"); + int found = 0; + //unsigned long sc; + + if (!tsk) + tsk = current; + + printk("tsk = %p,comm=%s,pid=%d,pgd=0x%p\n", tsk , tsk->comm , tsk->pid , tsk->mm->pgd ); + if (tsk == current) { + frame.fp = (unsigned long)__builtin_frame_address(0); + frame.sp = current_sp; + frame.lr = (unsigned long)__builtin_return_address(0); + frame.pc = (unsigned long)unwind_get_regs; + } else { + /* task blocked in __switch_to */ + frame.fp = thread_saved_fp(tsk); + frame.sp = thread_saved_sp(tsk); + /* + * The function calling __switch_to cannot be a leaf function + * so LR is recovered from the stack. + */ + frame.lr = 0; + frame.pc = thread_saved_pc(tsk); + } + + while (1) { + int urc; + //unsigned long where = frame.pc; + + urc = unwind_frame(&frame); + if (urc < 0) + break; + //dump_backtrace_entry(where, frame.pc, frame.sp - 4); + if( frame.pc == (unsigned long)ret_fast_syscall ){ + found = 1; + break; + } + } + if( !found ) + return NULL; + #if 0 + //printk("FRAME:sp=0x%lx,pc=0x%lx,lr=0x%lx,fp=0x%lx\n" , frame.sp,frame.pc,frame.lr,frame.fp ); + //rk28_printk_mem((unsigned int*)(frame.sp-sizeof(struct pt_regs)),2*sizeof(struct pt_regs)/4+8, NULL ); + sc =*( (unsigned long*)(frame.sp-4)); + if( sc >= (unsigned long)&_text && sc < (unsigned long)&_end ){ + print_symbol("sys call=%s\n",sc ); + } + #endif + return (struct pt_regs *)(frame.sp+8); // 8 for reg r4,r5 as fifth and sixth args. +} + +struct pt_regs * __scu_get_regs( void ) +{ + return unwind_get_regs( NULL ); +} + +struct pt_regs * scu_get_task_regs( int pid ) +{ + struct task_struct *t = FIND_TASK_BY_PID( pid ); + return unwind_get_regs( t ); +} + +/* + * f: bit0: show kernel , bit1: dump user. + */ +int tstack( int pid , int f) +{ + struct pt_regs * preg; + struct task_struct *t = FIND_TASK_BY_PID( pid ); + + if( !t ){ + printk("NO task found for pid %d\n" ,pid ); + t = current ; + } + preg = unwind_get_regs( t ); + if( f& 1 ) { + show_stack( t , NULL ); + } + if( !preg ) { + printk("NO user stack found for task %s(%d)\n" , t->comm , t->pid ); + } else { + //printk("user stack found for task %s(%d):\n" , t->comm , t->pid ); + __show_regs( preg ); + if( f & 2 ) { + #define SHOW_STACK_SIZE (2*1024) + int len; + unsigned int *ps = (unsigned int*)kmalloc( SHOW_STACK_SIZE , GFP_KERNEL); + if( ps ) { + len = access_process_vm( t , preg->ARM_sp , ps , SHOW_STACK_SIZE, 0 ); + rk28_printk_mem( ps , len/4 , (unsigned int* )preg->ARM_sp ); + kfree( ps ); + } + } + } + return pid; +} + +#if 0 +void __rk_force_signal(struct task_struct *tsk, unsigned long addr, + unsigned int sig, int code ) +{ + struct siginfo si; + printk("%s::send sig %d to task %s\n" , __func__ , sig , tsk->comm ); + si.si_signo = sig; + si.si_errno = 0; + si.si_code = code; + si.si_addr = (void __user *)addr; + force_sig_info(sig, &si, tsk); +} +int rksignal( int pid , int sig ) +{ + struct task_struct *t = FIND_TASK_BY_PID( pid ); + if( !t ) + t = current ; + __rk_force_signal( t , 0xc0002234 , sig , 0x524b4b52 ); + return 0x201; +} + +#include +#include +#include +extern struct console *console_drivers; +// like : echo rk28_uart_input,"\"pwd|ls,echo fdfdf\"">active +int rk28_uart_input( char * str ) +{ + char * p = str; + int indx; + struct tty_driver *tty_drv = console_drivers->device( console_drivers , &indx ); + struct tty_struct *tty_s = tty_drv->ttys[indx ]; + int flag = TTY_NORMAL; + + printk("indx=%d, tty drv=%p,tty_s=%p,cur console=%s,next console=%p\n", indx , tty_drv , tty_s , + console_drivers->name , console_drivers->next ); + //printk("cmd=%s\n" , str ); + if( !p ) + return -EIO; + + while( *p ) { + if( *p == ',' ) + *p = '\n'; + p++; + } + *p++ = '\n'; + *p = 0; + + p = str; + while( *p ) { + tty_insert_flip_char(tty_s, *p , flag); + p++; + } + + tty_flip_buffer_push( tty_s ); + return 0x28; +} +#endif + +#if 0 +extern int kernel_getlog( char ** start , int * offset , int* len ); +int rk28_write_file( char *filename ) +{ + char *procmtd = "/proc/mtd"; + struct file *filp = NULL; + loff_t pos; + long fd; + + ssize_t l=0; + char pathname[64]; + char buf[1024] ; + mm_segment_t old_fs; + struct rtc_time tm; + ktime_t now; + char *tmpbuf; + int mtdidx=0; + int mtdsize = 0x200000; // 2M + char *log_buf; + int log_len; + + debug_print("%s: filename=%s\n" , __func__ , filename ); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + fd = sys_open( procmtd , O_RDONLY , 0 ); + if( fd >= 0 ) { + memset( buf , 0 , 1024 ); + l = sys_read( fd , buf , 1024 ); + // debug_print("/proc/mtd,total byte=%d\n" , l ); + tmpbuf = strstr( buf , filename ); + if( tmpbuf ) { + tmpbuf[10] = 0; + mtdsize = simple_strtoul(tmpbuf-19, NULL , 16); + mtdidx = tmpbuf[-22]; + //debug_print("size=%s\n,idx=%s\nmtdsize=%x , mtdidx=%d" , tmpbuf-19 , tmpbuf - 22 , + // mtdsize , mtdidx ); + mtdsize *= 512; + mtdidx -= '0'; + } + sys_close( fd ); + } else { + debug_print("open %s failed\n" , procmtd ); + } + sprintf(pathname , "/dev/block/mtdblock%d" , mtdidx ); + filp = filp_open(pathname, O_WRONLY , 0); + if( IS_ERR(filp) ) { + debug_print("open %s failed n" , pathname ); + goto out_print; + } + if (!(filp->f_op->write || filp->f_op->aio_write)) { + debug_print("can not write file %s \n" , pathname ); + goto close_file; + } + now = ktime_get(); + rtc_time_to_tm( now.tv.sec , &tm ); + printk( "\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + "++++++++++RECORD LOG AT %04d-%02d-%02d %02d:%02d:%02d++++++++++\n" + "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n\n" + , + tm.tm_year+1900 , tm.tm_mon , tm.tm_mday , tm.tm_hour , tm.tm_min , tm.tm_sec ); + /* 20090924,HSL,FTL only intial first 256M at loader , MUST write 32 sector one time */ + //debug_print("write first pack , pos=%d\n" , pos ); /* pos = 2 ?? */ + kernel_getlog(&log_buf , NULL , &log_len ); + log_len = (log_len+(32*512-1)) / (32*512) * (32*512); + pos = 0; + l = vfs_write( filp , log_buf , log_len , &pos ); + do_fsync(filp, 1); +close_file: + filp_close(filp , NULL); +out_print: + set_fs(old_fs); + debug_print("\nlog len=%d,write=%d\n" ,log_len , l); + return 0x2b; +} +#endif + +#if 1 +/* + * + * 20091027,2808SDK, + * lcd off:byte:81748000,word:39100000. + * lcd on: byte:90742000,word:43158000 %9.5 + * + * 20091111,2806 ruiguan, + * lcd off: byte: 81883000,word: 39209000 + * lcd on: byte: 90843000,word: 43260000 + + * 20100516,281x, 133 ddr , lcd on. + * need 151432000 ns to copy 4096 Kbytes + * need 85340000 ns to copy 1024 Kwords + LCD OFF. + * need 144880000 ns to copy 4096 Kbytes + * need 83100000 ns to copy 1024 Kwords + 20100517,281x,200M ddr lcd on. + * need 90024000 ns to copy 4096 Kbytes + * need 47668000 ns to copy 1024 Kwords + lcd off + need 87564000 ns to copy 4096 Kbytes + need 46956000 ns to copy 1024 Kwords + 20100518,266M ddr. lcd on + need 84460000 ns to copy 4096 Kbytes + need 41036000 ns to copy 1024 Kwords + + need 204568000 ns to copy 4096 Kbytes +need 116388000 ns to copy 1024 Kwords + + ddr 330M,lcd on. + need 81944000 ns to copy 4096 Kbytes + need 37640000 ns to copy 1024 Kwords + ahb 180M.ddr 330M. + need 88908000 ns to copy 4096 Kbytes + need 38108000 ns to copy 1024 Kwords + + ahb 200M,DDR 380M,lcd on. + need 79456000 ns to copy 4096 Kbytes + need 34216000 ns to copy 1024 Kwords %0.14. + + need 79432000 ns to copy 4096 Kbytes +need 34204000 ns to copy 1024 Kwords +LCD OFF. + need 77260000 ns to copy 4096 Kbytes + need 33768000 ns to copy 1024 Kwords + + need 77228000 ns to copy 4096 Kbytes +need 33764000 ns to copy 1024 Kwords %0.01 + */ + +/* +on rk29 +dyn desktop: +[ 63.010000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 63.100000] need 90342667 ns to copy 4096 Kbytes +[ 63.140000] need 38885333 ns to copy 1024 Kwords +[ 63.160000] need 13030791 ns to memcpy 4096 Kbytes +[ 63.160000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 65.680000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 65.740000] need 57542915 ns to copy 4096 Kbytes +[ 65.770000] need 30017666 ns to copy 1024 Kwords +[ 65.810000] need 32929083 ns to memcpy 4096 Kbytes +[ 65.810000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 67.400000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 67.460000] need 52001876 ns to copy 4096 Kbytes +[ 67.490000] need 29809209 ns to copy 1024 Kwords +# [ 67.510000] need 20318709 ns to memcpy 4096 Kbytes +[ 67.510000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 71.800000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 71.860000] need 57265835 ns to copy 4096 Kbytes +[ 71.900000] need 32522127 ns to copy 1024 Kwords +[ 71.930000] need 27615668 ns to memcpy 4096 Kbytes +[ 71.930000] @return 0x2c(44) + + +static desktop: + +[ 171.880000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 171.910000] need 27547043 ns to copy 4096 Kbytes +[ 171.920000] need 8993501 ns to copy 1024 Kwords +[ 171.930000] need 6791584 ns to memcpy 4096 Kbytes +[ 171.930000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 174.050000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 174.080000] need 26437334 ns to copy 4096 Kbytes +[ 174.090000] need 8701667 ns to copy 1024 Kwords +[ 174.100000] need 6639375 ns to memcpy 4096 Kbytes +[ 174.100000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 176.290000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 176.320000] need 26692502 ns to copy 4096 Kbytes +[ 176.330000] need 8659126 ns to copy 1024 Kwords +[ 176.340000] need 6702001 ns to memcpy 4096 Kbytes +[ 176.340000] @return 0x2c(44) +# echo rk28_memcpy > cal +[ 177.710000] @CALL@ rk28_memcpy(0xc070148c),argc=0 +[ 177.740000] need 27578291 ns to copy 4096 Kbytes +[ 177.750000] need 8740042 ns to copy 1024 Kwords +[ 177.760000] need 6727458 ns to memcpy 4096 Kbytes +[ 177.760000] @return 0x2c(44) + +*/ +int rkmemcpy( void ) +{ +#define PAGE_ORDER 7 + ktime_t now0,now1; + + unsigned long pg; + unsigned long src = 0xc0010000; + int i = 8,k=0; + int bytes = ((1< 20 ) + loop = 20; + do { + ktime_now = ktime_get(); + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + printk("now=%lld ns " + "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", + ktime_to_ns(ktime_now), + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); + udelay( 31 ); + loop --; + }while( loop > 0 ); + return 0x2c; +} + +#if 0 +/* 1,2=0 , 0 = lr */ +void rk28_return( void ) +{ + printk("return addr:\n 0: 0x%p " "1: 0x%p " "2: 0x%p\n", __builtin_return_address(0) , + __builtin_return_address(1) , __builtin_return_address(2)); +} +#endif + +int dl( int ms ) +{ + mdelay( ms ); + printk("delay %d ms\n" , ms ); + return ms; +} + +int irq_dl( int ms ) +{ + unsigned long flags; + local_irq_save(flags); + mdelay( ms ); + local_irq_restore(flags); + printk("delay %d ms\n" , ms ); + return ms; +} + +/* + * read a phy addr value , len is word. +*/ +int dd( unsigned int phy_addr,int len ,unsigned int value ) +{ + int size = len*4; + unsigned int * ptr; + int wr = 0; + int map = 0; + if( !len ){ + printk("invalid len=%d\n" , len ); + return 0; + } + /* we want to write? write 0?*/ + if( value || len == 1 ) { + size = 4; + wr = 1; + } + if(phy_addr < PAGE_OFFSET ) { + ptr = (unsigned int *)ioremap( phy_addr , size ); + if( !ptr ) { + printk("map addr 0x%x failed\n" , phy_addr ); + return -ENOMEM; + } + map = 1; + } else { + ptr = (unsigned int *)phy_addr; + } + if( wr ) { + *ptr = value ; + dmb(); + } + rk28_printk_mem( ptr , len , (unsigned int*)phy_addr ); + if( map ) { + iounmap(ptr); + } + return size; +} + diff --git a/drivers/dbg/kobj.c b/drivers/dbg/kobj.c new file mode 100644 index 000000000000..423d145abc8b --- /dev/null +++ b/drivers/dbg/kobj.c @@ -0,0 +1,100 @@ +/* + * kobj.c + * + * (C) Copyright hsl 2009 + * Released under GPL v2. + * + * + * log: + * for debug function by sysfs + * + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct kobject *dbg_kobj; + +extern int dbg_parse_cmd( char * cdb ); + +static char dbg_lastcmd[512]; + +/* default kobject attribute operations */ +static ssize_t dbg_call_attr_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + strcpy( buf , dbg_lastcmd ); + strcat(buf,"\n"); + return strlen(buf)+1; +} +static ssize_t dbg_call_attr_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + char cmd[512]; + int len = sizeof(dbg_lastcmd)>count ? count:sizeof(dbg_lastcmd); + //printk("count=%d,cmd=%s!\n" , count , buf ); + strncpy( dbg_lastcmd , buf , len ); + if( dbg_lastcmd[len-1] == '\n' ){ + dbg_lastcmd[len-1] = 0; + len--; + } + strncpy( cmd , dbg_lastcmd , sizeof(cmd) ); + dbg_parse_cmd( cmd ); + return count; +} + + + +static struct kobj_attribute _call_attr = { + .attr = { + .name = "dbg", + .mode = 0644, + }, + .show = dbg_call_attr_show, + .store = dbg_call_attr_store, +}; + +static struct attribute * g[] = { + &_call_attr.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = g, +}; + + +int dbg_init( void ) +{ + //dbg_kobj = kobject_create_and_add("dbg", NULL ); /*kernel_kobj*/ + //if (!dbg_kobj) + // return -ENOMEM; + //return sysfs_create_group(dbg_kobj, &attr_group); + return sysfs_create_group(kernel_kobj, &attr_group); +} + +late_initcall(dbg_init); + diff --git a/drivers/dbg/wrapcall.S b/drivers/dbg/wrapcall.S new file mode 100644 index 000000000000..01805046cc98 --- /dev/null +++ b/drivers/dbg/wrapcall.S @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#__scu_call_wrap: +# +# call to the defined funcion. +# r0: func argument array , max = 6 +# r1: argument num. +# r2: the function number. + +#; EXPORT __scu_call_wrap +#; +#; CODE32 +#; AREA ||funwrap||, CODE, READONLY +ENTRY(__scu_call_wrap) + STMFD r13!,{r4,r5,r6,lr} + mov r6,r2 + ldmia r0, {r0-r5} + STMFD r13!,{r4,r5} + mov lr , pc + mov pc , r6 + add r13 , r13 ,#8 + LDMFD r13!,{r4,r5,r6,pc} + +/** + * 20091126,HSL@RK,change to get syscall struct pt_regs *. + * way: search stack frame for lr = ret_fast_syscall. + * code from bachtrace.S -- __backtrace. + * 20110126,not support at 2.6.32(no fp) + * 20110127,support at debug.c,use c funtion. + */ +#define frame r4 +#define sv_fp r5 +#define sv_pc r6 +#define mask r7 +#define offset r8 +/* +ENTRY(__scu_get_usr_regs) + mov r0, #0 + mov pc, lr +*/ + +/* + * 20091215,continue running from break point. + * r0 is the struct pt_regs *. + */ +ENTRY(__scu_bk_continue) + mov r12, r0 + ldr r0, [r12, #S_PSR] + msr spsr_cxsf, r0 + ldmia r12, {r0 - pc}^ @ load r0 - pc, cpsr + +#if FIQ_ENABLE + .align +ENTRY(rk28_fiq_handle) + mrs r8, spsr + adr r9,__fiq_save + stmia r9 , {r0-r8,lr} + mov r0,r9 @save addr. + mov r5,#(SVC_MODE|PSR_I_BIT|PSR_F_BIT) + msr cpsr_cxsf,r5 @ to svc mod.disable irq,fiq. + sub r1, sp, #(S_FRAME_SIZE) + + add r2 , r1 , #32 @ r0--r7. + stmia r2,{r8-lr} @ the svc sp not change here. + ldmia r0,{r3-r10} + stmia r1,{r3-r10} + ldr r9,[r0,#36] @get fiq lr. + sub r9,r9,#4 + str r9 , [r1,#S_PC] + ldr r10,[r0,#32] @get fiq spsr. + str r10, [r1,#S_PSR] + mov r5,r1 + mov sp,r5 @stack frame + mov r0,r5 + ldr r11,1f + blx r11 + b 3f +1: + .long rk28_debug_fiq +3: + msr spsr_cxsf,r10 + ldmia r5, {r0 - pc}^ +__fiq_save: @for save fiq spsr r0-r7,spsr,lr. + .long 0 + .previous +#endif + -- 2.34.1