mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
HSL: dbg:add some debug function
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -115,3 +115,5 @@ obj-$(CONFIG_STAGING) += staging/
|
||||
obj-y += platform/
|
||||
obj-y += ieee802154/
|
||||
obj-$(CONFIG_CMMB) += cmmb/
|
||||
obj-y += dbg/
|
||||
|
||||
|
||||
7
drivers/dbg/Makefile
Normal file
7
drivers/dbg/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Makefile for rk_scu drivers.
|
||||
#
|
||||
obj-y :=wrapcall.o debug.o kobj.o
|
||||
|
||||
|
||||
|
||||
690
drivers/dbg/debug.c
Normal file
690
drivers/dbg/debug.c
Normal file
@@ -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 <linux/kallsyms.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
/*
|
||||
* 20090725,hsl,some debug function start from here
|
||||
*/
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#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 <linux/tty.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty_flip.h>
|
||||
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<<PAGE_ORDER)*PAGE_SIZE);
|
||||
|
||||
pg = __get_free_pages(GFP_KERNEL , PAGE_ORDER );
|
||||
if( !pg ) {
|
||||
printk("alloc %d pages total %dK bytes failed\n" , (1<<PAGE_ORDER) , bytes/(1024));
|
||||
return -ENOMEM;
|
||||
}
|
||||
now0 = ktime_get();
|
||||
while( k < i ) {
|
||||
char *p = (char*)pg;
|
||||
char *q = (char*)src;
|
||||
char *m = q+bytes;
|
||||
while( q < m )
|
||||
*p++ = *q++;
|
||||
k++;
|
||||
}
|
||||
now1 = ktime_get();;
|
||||
printk("need %Ld ns to copy %d Kbytes \n" ,
|
||||
ktime_to_ns( ktime_sub( now1 , now0 ) ), bytes * i /1024 );
|
||||
now0 = ktime_get();
|
||||
k = 0;
|
||||
while( k < i ) {
|
||||
int *p = (int*)pg;
|
||||
int *q = (int*)src;
|
||||
int *m = q+bytes/sizeof(int);
|
||||
while( q < m )
|
||||
*p++ = *q++;
|
||||
k++;
|
||||
}
|
||||
now1 = ktime_get();
|
||||
|
||||
printk("need %Ld ns to copy %d Kwords \n" ,
|
||||
ktime_to_ns( ktime_sub( now1 , now0 ) ), bytes * i / sizeof (int) /1024 );
|
||||
|
||||
now0 = ktime_get();
|
||||
for( k = 0 ; k < i ; k++ )
|
||||
memcpy((void*)pg,(void*)src , bytes );
|
||||
now1 = ktime_get();
|
||||
printk("need %Ld ns to memcpy %d Kbytes \n" ,
|
||||
ktime_to_ns( ktime_sub( now1 , now0 ) ), bytes * i / 1024 );
|
||||
|
||||
free_pages( pg , PAGE_ORDER );
|
||||
return 0x2c;
|
||||
}
|
||||
#endif
|
||||
|
||||
int rknow( int loop , int prtk )
|
||||
{
|
||||
ktime_t ktime_now;
|
||||
struct timespec ts;
|
||||
struct rtc_time tm;
|
||||
|
||||
if( loop > 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;
|
||||
}
|
||||
|
||||
100
drivers/dbg/kobj.c
Normal file
100
drivers/dbg/kobj.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* kobj.c
|
||||
*
|
||||
* (C) Copyright hsl 2009
|
||||
* Released under GPL v2.
|
||||
*
|
||||
*
|
||||
* log:
|
||||
* for debug function by sysfs
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
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);
|
||||
|
||||
94
drivers/dbg/wrapcall.S
Normal file
94
drivers/dbg/wrapcall.S
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/glue.h>
|
||||
#include <asm/vfpmacros.h>
|
||||
#include <asm/thread_notify.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
#__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
|
||||
|
||||
Reference in New Issue
Block a user