TQ2440 自制系统调用ORW
TQ2440 自制系统调用ORW
======================
注意: 这个开发板linux系统是 linux-2.6.22.4
======================
原理图:

========================
内核简单说明
1. 在Source Insight 搜索 "vector_swi",可跟踪原理
右击-> Lookup Reference
2. 可查看到 linux-2.6.30.4\arch\arm\kernel\entry-common.S 有内容"vector_swi"
ENTRY(vector_swi) // 红色地带1 : 保留现场 sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 add r8, sp, #S_PC stmdb r8, {sp, lr}^ @ Calling sp, lr mrs r8, spsr @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC] @ Save calling PC str r8, [sp, #S_PSR] @ Save CPSR str r0, [sp, #S_OLD_R0] @ Save OLD_R0 zero_fp /* * Get the system call number. */ #if defined(CONFIG_OABI_COMPAT) /* * If we have CONFIG_OABI_COMPAT then we need to look at the swi * value to determine if it is an EABI or an old ABI call. */ #ifdef CONFIG_ARM_THUMB tst r8, #PSR_T_BIT movne r10, #0 @ no thumb OABI emulation ldreq r10, [lr, #-4] @ get SWI instruction #else /** 红色地带2 * 1. lr寄存器-4等于发生异常的那条指令的地址(机器码) SWI地址(SWI instruction) * 2. 检查 SWI的机器码是不是SWI的指令,开头是否为0x0f000000( 2440手册),如果是则是SWI指令 */ ldr r10, [lr, #-4] @ get SWI instruction A710( and ip, r10, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) #endif #elif defined(CONFIG_AEABI) /* * Pure EABI user space always put syscall number into scno (r7). */ A710( ldr ip, [lr, #-4] @ get SWI instruction ) A710( and ip, ip, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) #elif defined(CONFIG_ARM_THUMB) ... ... #ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment ldr ip, [ip] mcr p15, 0, ip, c1, c0 @ update control register #endif enable_irq /* 红色地带3 * 2. 系统调用函数的数组(syscall) */ get_thread_info tsk adr tbl, sys_call_table @ load syscall table pointer ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing ... ... #if defined(CONFIG_OABI_COMPAT) /* * If the swi argument is zero, this is an EABI call and we do nothing. * * If this is an old ABI call, get the syscall number into scno and * get the old ABI syscall table address. */ bics r10, r10, #0xff000000 eorne scno, r10, #__NR_OABI_SYSCALL_BASE ldrne tbl, =sys_oabi_call_table #elif !defined(CONFIG_AEABI) /* 红色地带4 * 1.2. 清楚高8位,留下后面24位=val=0x900001, 有个异或过程(eor) */ bic scno, scno, #0xff000000 @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif stmdb sp!, {r4, r5} @ push fifth and sixth args tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? bne __sys_trace /* 红色地带 5 * 3. 基地址+scno(val), 左移2位 */ cmp scno, #NR_syscalls @ check upper syscall limit adr lr, ret_fast_syscall @ return address ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine ... ... ENDPROC(vector_swi)
ps: 上面代码 CONFIG_OABI_COMPAT; CONFIG_AEABI部分可查找内核 .config配置文件,如果没有,即是内核用不到的代码段,上面代码注意 红色地带 代码
====================================
内核简单说明
1.Source Insight 搜索"sys_write",得到下面3个文件
linux-2.6.22.4\arch\arm\kernel\calls.S linux-2.6.2.4\fs\read_write.c linux-2.6.22.4\include\linux\syscalls.h
1.calls.S文件
/* 350 */ CALL(sys_timerfd) CALL(sys_eventfd) CALL(sys_hello) #ifndef syscalls_counted .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
2.read_write.c
return ret; } asmlinkage void sys_hello(const char __user * buf, int count) { char ker_buf[100]; if (buf) { copy_from_user(ker_buf, buf, (count < 100) ? count : 100); ker_buf[99] = '\0'; printk("sys_hello: %s\n", ker_buf); } } asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
3.syscalls.h
asmlinkage ssize_t sys_write(unsigned int fd, const char __user *buf, size_t count); asmlinkage void sys_hello(const char __user * buf, int count); asmlinkage ssize_t sys_writev(unsigned long fd,
以上红色字体为内核文件新添加部分
4. 测试程序 --\test_system_call.c
#include <errno.h> #include <unistd.h> //#include <sysdep.h> //#if defined(__thumb__) || defined(__ARM_EABI__) //#define __NR_SYSCALL_BASE 0 //#else #define __NR_SYSCALL_BASE 0x900000 //#endif void hello(char *buf, int count) { /* swi */ asm ("mov r0, %0\n" /* save the argment in r0 */ "mov r1, %1\n" /* save the argment in r0 */ "swi %2\n" /* do the system call */ : : "r"(buf), "r"(count), "i" (__NR_SYSCALL_BASE + 352) : "r0", "r1"); } int main(int argc, char **argv) { printf("in app, call hello\n"); hello("www.100ask.net", 15); return 0; }
5. 以上,将前面3个修改后的文件更新到内核并编译, 同时编译测试程序并拷贝大开发板
# make
# arm-linux-gcc -o test_system_call test_system_call.c
# cp test_system_call /opt/share
6. 如果用未修改的内核运行测试程序,则是下面情况

7. 用修改后的内核,如下

============================
指令地址反推
下图1 - 2440文档文件 SOFTWARE INTERRUPT(SWI)

下图2 - 反汇编文件

由上面两图可以看出:
图2 黑色部分的 ef900160 swi 0x00900160 e: 无条件执行 f : 有图1的(27-24)bit都为1, 即为f, 表示 swi指令 900160: 即是后面的val为0x00900160
============================
--------------- The end !!
 
 
 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号