ARM Linux: Implementation principle of switching from usr mode to svc mode

Publisher:RadiantJourneyLatest update time:2020-07-23 Source: elecfansKeywords:ARM  Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Everyone knows that if a Linux application wants to access the kernel, it must use a system call to switch from usr mode to svc mode. Let's take a look at its implementation process.


System call is a service provided by the OS operating system. User programs use various system calls to reference various services provided by the kernel. The execution of system calls causes user programs to fall into the kernel, and the falling action is completed by the SWI soft interrupt.


The soft interrupt corresponding to the Linux 2.4.19 kernel system call corresponding to the at91rm9200 processor is defined as follows:

#if defined(__thumb__) //thumb模式

#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 the OS_NUMBER "" 20 operation value

#define __NR_open (__NR_SYSCALL_BASE+ 5) //0x900005


For example, the open system call, the library function will eventually call __syscall (open), which is expanded to swi #__NR_open after macro expansion, that is, swi #0x900005 triggers an interrupt, and the interrupt number 0x900005 is stored in the address [lr, #-4]. The processor jumps to vector_swi in arch/arm/kernel/entry-common.S to read the interrupt number in the address [lr, #-4], and then queries the sys_call_table system call table in arch/arm/kernel/entry-common.S. The content of this table is defined in arch/arm/kernel/calls.S, and the corresponding sequence number of __NR_open in the table is

__syscall_start:

。。.

.long SYMBOL_NAME(sys_open) //5th

。。.

The content in sys_call_table[5] is passed to pc, and the system enters the sys_open function to process the actual open action.

Note: The files where some function data are used are as follows

arch/arm/kernel/calls.S declares the system call function

include/asm-arm/unistd.h defines the call number rules for system calls

vector_swi is defined in arch/arm/kernel/entry-common.S

vector_IRQ is defined in arch/arm/kernel/entry-armv.S

vector_FIQ is defined in arch/arm/kernel/entry-armv.S

sys_call_table is defined in arch/arm/kernel/entry-common.S:

.type sys_call_table, #object

ENTRY(sys_call_table)

#include "calls.S" //Link the contents of calls.S here in sequence

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 fifth 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 open system call number in the above example, scno=0x900005

//eor scno,scno,#0x900000

//After that scno=0x05

eor scno, scno, #OS_NUMBER 《《 20 @ check OS number

//The sys_call_table item is the content of calls.S

adr tbl, sys_call_table @ load syscall table pointer

tst ip, #PT_TRACESYS @ are we tracing syscalls?

bne __sys_trace

adrsvc al, lr, ret_fast_syscall @ return address

cmp scno, #NR_syscalls @ check upper syscall limit

//Execute sys_open function

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, #ARMSWI_OFFSET

eor r0, 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 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)

/*

//2007-07-01 gliethttp [entry-header.S]

//Like adr, but force SVC mode (if required)

.macro adrsvc, cond, reg, label

adr/cond /reg, /label

.endm

//Corresponding 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_syscalls @ 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, #object

ENTRY(sys_call_table)

#include “calls.S”

Keywords:ARM  Linux Reference address:ARM Linux: Implementation principle of switching from usr mode to svc mode

Previous article:ARM architecture: How to pass more than four function call parameters
Next article:The difference and usage of ARM function pointer and pointer function

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号