Detailed analysis of ARM Linux System Call process-SWI

Source: Internet
Author: User

From: http://www.diybl.com/course/6_system/linux/Linuxjs/20090515/167024.html

A Unix system sends a system call to the kernel to implement most interfaces between user-mode processes and hardware devices. System calls are services provided by the operating system. User Programs reference various services provided by the kernel through various system calls. The execution of system calls puts user programs into the kernel, this is completed by SWI soft interruption.

The difference between an application programming interface (API) and a system call is that the former is just a function definition and describes how to obtain a given service, the latter is a clear request sent to the kernel through software interruption. The POSIX standard is applicable to APIs rather than system calls. The UNIX system provides many api library functions for programmers. Some APIs defined in the Standard C library of libc reference wrapper routine (the sole purpose of which is to publish system calls ). Generally, each system call corresponds to an encapsulation routine, which defines the API used by the application. Otherwise, an API does not need to be called by a specific system. From the programmer's point of view, the difference between APIs and system calls is irrelevant: The only thing that is relevant is the function name, parameter type, and the meaning of the return code. However, from the kernel designer's point of view, this difference does matter because system calls belong to the kernel, and user-state library functions do not belong to the kernel.

Most encapsulation routines return an integer. The meaning of the value depends on the corresponding system call. -1 usually indicates that the kernel cannot meet the process request. The failure of the system call handler may be caused by Invalid parameters, or because of the lack of available resources or hardware problems. The errno variable defined in the libd library contains a specific error code. Each error code is defined as a constant macro.

When a user-state process calls a system call, the CPU switches to the kernel state and runs a kernel function. Because the kernel implements many different system calls, the process must pass a parameter named system call number to identify the required system calls. An integer is returned for all system calls. These return values are different from the conventions for encapsulating the return values of routines. In the kernel, an integer or 0 indicates the successful completion of the system call, while a negative number indicates an error condition. In the latter case, this value is the negative error code that must be returned to the application in the errno variable.

ArmLinux uses the SWI command to enter the kernel space from the user space. Let's take a look at this SWI command first. SWI commands are used to generate software interruptions, so as to transform the user mode to the management mode, save cpsr to the spsr in the management mode, and transfer the execution to the SWI vector. SWI commands can be used in other modes, and the processor switches to the management mode. The command format is as follows:

SWI {cond} immed_24

Where:

Immed_2424-digit immediate number, which is an integer ranging from 0 to 16777215.

When SWI commands are used, two methods are usually used for parameter passing. SWI exception handlers can provide related services, both of which are user software agreements. The SWI exception interrupt handling program reads the SWI command that causes the software interruption and obtains 24 as the immediate number.

1) The 24-bit immediate number in the command specifies the service type of the user request, and the parameter is passed through the General Register. For example:

MoV r0, #34

SWI 12

2) The 24-bit immediate number in the command is ignored. The service type requested by the user is determined only by the register r0, and the parameter is passed through other General registers. For example:

MoV r0, #12

MoV R1, #34

SWI 0

In the SWI exception handling program, the steps to remove the immediate Number of SWI are as follows: First, determine whether the arm command is a thumb command when a SWI command is soft interrupted, which can be obtained through spsr access; then obtain the address of the SWI command, which can be obtained by accessing the LR register; then read the command and break down the immediate number (24 bits low ).

 

The following code can be found in entry-common.S.

In section 2.6.21, you will find that you cannot avoid this concept. What is Eabi?

In the kernel, the interview with Eabi and oabi is actually relative to the method of system calling. Of course, the system we call is limited to the arm system.
Eabi (Extended Abi) is a new method of calling the system.

MoV R7, # num
SWI 0x0

The original system call method is as follows,
SWI (# num | 0x900000) (0x900000 is a magic value)

That is to say, the original call method (old Abi) is implemented by following the call number in the SWI command. Now it is based on the value in R7.

Now let's look at two macros. One is
Config_oabi_compat indicates compatibility with the old Abi.

The other is
Config_aeabi indicates specifying the current method as Eabi.

These two macros can be configured at the same time, neither deserve nor can be configured.

Let me talk about how the kernel handles this problem.
We know that sys_call_table is a jump table in the kernel, which stores a series of function pointers. These pointers are the pointers of the system-called functions, such as sys_open ). the system calls a function based on the call number (usually the index of the table) to find the function that actually calls the kernel, and then runs the function.

First, for the old Abi, the kernel creates a separate system call table called sys_oabi_call_table for it. In this way, there will be two System Call tables in compatibility mode, system calls in the old Abi mode will execute the system call function in the old_syscall_table table. system calls in the Eabi mode will use the function pointer in sys_call_table.

No more than 4

The configuration behavior of the first two macros is as described above.

Second, only config_oabi_compat is configured. sys_oabi_call_table will be used for calling in the old Abi method. sys_call_table called in the Eabi method is essentially the same as 1, but case 1 is clearer.

Third, configure that the config_aeabi system does not contain sys_oabi_call_table, which is incompatible with calling the old Abi method. It can only be called in Eabi mode, with sys_call_table

If neither of them is configured, the system only allows the old Abi method by default, but the old_syscall_table does not exist, function calling will be completed through sys_call_table.

Refer to the following code.
It is useful for our projects.

.align 5 ENTRY(vector_swi) 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 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) /* Legacy ABI only, possibly thumb mode. */ tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in ldreq scno, [lr, #-4] #else /* Legacy ABI only. */ ldr scno, [lr, #-4] @ get SWI instruction A710( and ip, scno, #0x0f000000 @ check for SWI ) A710( teq ip, #0x0f000000 ) A710( bne .Larm710bug ) #endif #ifdef CONFIG_ALIGNMENT_TRAP ldr ip, __cr_alignment ldr ip, [ip] mcr p15, 0, ip, c1, c0 @ update control register #endif enable_irq 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) 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 cmp scno, #NR_syscalls @ check upper syscall limit adr lr, ret_fast_syscall @ return address ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine add r1, sp, #S_OFF 2: mov why, #0 @ no longer a real syscall cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back bcs arm_syscall b sys_ni_syscall @ not private func /* * This is the really slow path. We're going to be doing * context switches, and waiting for our parent to respond. */ __sys_trace: mov r2, scno add r1, sp, #S_OFF mov r0, #0 @ trace entry [IP = 0] bl syscall_trace adr lr, __sys_trace_return @ return address mov scno, r0 @ syscall number (possibly new) add r1, sp, #S_R0 + S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit ldmccia r1, {r0 - r3} @ have to reload r0 - r3 ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine 

 

System calling is a service provided by the operating system of the operating system. User Programs reference various services provided by the kernel through various system calls. The execution of system calls puts user programs into the kernel, this is completed by the SWI Soft Interrupt.

The Soft Interrupt definitions for Linux kernel system calls corresponding to the at91rm9200 processor are as follows:

# If defined (_ thumb _) // thumb mode # DEFINE _ syscall (name) \ "Push {R7} \ n \ t" \ "mov R7, # "_ sys1 (_ nR _ # name) "\ n \ t" \ "SWI 0 \ n \ t" \ "Pop {R7}" # else // arm mode # DEFINE _ syscall (name) "SWI \ t" _ sys1 (_ nR _ # Name) "\ n \ t" # endif # DEFINE _ sys2 (X) # X # DEFINE _ sys1 (x) _ sys2 (X) # DEFINE _ nr_syscall_base 0x900000 // This is OS _number <20 operation value # DEFINE _ nr_open (_ nr_syscall_base + 5) // 0x900005

 

For example, when an open system is called, the library function will eventually call _ syscall (Open). After the macro is expanded, it is SWI #__ nr_open, that is, SWI #0x900005 triggers the interruption, interrupt number 0x900005 stored in [LR, #-4] address, processor jump to arch/ARM/kernel/entry-common.S vector_swi read the interrupt number in [LR, #-4] address, then query the sys_call_table system call table in the arch/ARM/kernel/entry-common.S. defined in S, __nr_open corresponds to the sequence number in the table

_ Syscall_start:

. Long symbol_name (sys_open) // 5th... pass the content in sys_call_table [5] to the PC, and the system enters the sys_open function to process the actual open action. Note: The files of some function data used are as follows: ARCH/ARM/kernel/call. s declares the system call function include/ASM-arm/unistd. h defines the call number rules for system calls vector_swi defined in arch/ARM/kernel/entry-common.Svector_IRQ defined in arch/ARM/kernel/entry-armv.Svector_FIQ defined in arch/ARM/kernel/entry-armv.Sarch/ARM/ sys_call_table is defined in the kernel/entry-common.S :. type sys_call_table, # objectentry (sys_call_table) # include "CILS. s "// set CILS. the content in S is sequentially linked to here

 

Source program:

Entry (vector_swi) save_user_regs zero_fp get_scno // dump the interrupt number in [LR, #-4] To scno (r7) arm710_bug_check scno, IP # ifdef config_alignment_trap ldr ip, _ cr_alignment ldr ip, [IP] MCR P15, 0, IP, C1, C0 @ update control register # endif enable_irq ip str R4, [Sp, #-s_off]! @ Push every th Arg get_current_task tsk ldr ip, [Tsk, # tsk_ptrace] @ check for syscall tracing Bic scno, scno, #0xff000000 @ mask off SWI op-code // # define OS _number 9 [entry-header.S] // so for the above example open system call number scno = 0x900005 // EOR scno, scno, #0x900000 // and then scno = 0x05 EOR scno, scno, # OS _number <20 @ check OS number // sys_call_table indicates CILS. s content adr tbl, sys_call_table @ load syscall table pointer tst ip, # pt_trac Esys @ are we tracing syscils? BNE _ sys_trace adrsvc Al, LR, ret_fast_syscall @ return address CMP scno, # nr_syscils @ check upper syscall limit // execute the sys_open function ldrcc PC, [TBL, scno, LSL #2] @ call sys _ * routine add R1, SP, # s_off2: mov why, #0 @ no longer a real syscall CMP scno, # armswi_offset er0 or, scno, # OS _number <20 @ put OS number back BCS symbol_name (arm_syscall) B symbol_name (sys_ni_syscall) @ not private func /** This is the really slow path. we're re going to be doing * context switches, and waiting for our parent to respond. */_ sys_trace: Add R1, SP, # s_off mov r0, #0 @ trace entry [IP = 0] BL symbol_name (syscall_trace) // gliethttp [entry-header.S] // like ADR, but force SVC mode (if required ). macro adrsvc, Cond, Reg, label ADR \ cond \ Reg, \ label. endm // disassembly: // Add LR, PC, #16; LR = _ sys_trace _ Return */adrsvc Al, LR, _ sys_trace_return @ return address add R1, SP, # s_r0 + s_off @ pointer to regs CMP scno, # nr_syscils @ check upper syscall limit ldmccia R1, {R0-R3} @ have to reload R0-R3 ldrcc PC, [TBL, scno, LSL #2] @ call sys _ * routine B 2B _ sys_trace_return: Str r0, [Sp, # s_r0 + s_off]! @ Save returned R0 mov R1, SP mov r0, #1 @ trace exit [IP = 1] BL symbol_name (syscall_trace) B ret_disable_irq. align 5 # ifdef config_alignment_trap. type _ cr_alignment, # object _ cr_alignment :. word symbol_name (cr_alignment) # endif. type sys_call_table, # objectentry (sys_call_table) # include "CILS. s"

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.