A brief analysis of the implementation of system calls under Linux based on ARM

Publisher:心灵舞者Latest update time:2020-02-16 Source: eefocusKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

In Linux, system calls are implemented using soft interrupts. The following uses a simple open example to briefly analyze how the application layer's open calls sys_open in the kernel.


t8.c


   1:  #include

   2:  #include

   3:  #include

   4:  #include

   5:   

   6:  int main(int argc, const char *argv[])

   7:  {

   8:      int fd;

   9:   

  10:      fd = open(".", O_RDWR);

  11:   

  12:      close(fd);

  13:      return 0;

  14:  }


It should be noted here that open is a library function provided by the C library, not a system call. System calls are in kernel space and cannot be called directly by application space. In "Linux Kernel Design and Implementation", it is said that to access the system call (often called syscall in Linux), it is usually done through a function call defined in the C library.


Compile t8.c statically, then disassemble it and see how open is called.


   1:  arm-linux-gcc t8.c --static

   2:  arm-linux-objdump -D a.out >a.dis


Below we intercept a part of a.dis for illustration:


   1:  ......

   2:  00008228

:

   3:      8228:   e92d4800    push    {fp, lr}

   4:      822c:   e28db004    add fp, sp, #4  ; 0x4

   5:      8230:   e24dd010    sub sp, sp, #16 ; 0x10

   6:      8234:   e50b0010    str r0, [fp, #-16]

   7:      8238:   e50b1014    str r1, [fp, #-20]

   8:      823c:   e59f0028    ldr r0, [pc, #40]   ; 826c

   9:      8240:   e3a01002    mov r1, #2  ; 0x2   ;  #define  O_RDWR  00000002 

  10:      8244:   eb002e7d    bl  13c40 <__libc_open>

  11:      8248:   e1a03000    mov r3, r0

  12:      824c:   e50b3008    str r3, [fp, #-8]

  13:      8250:   e51b0008    ldr r0, [fp, #-8]

  14:      8254:   eb002e9d    bl  13cd0 <__libc_close>

  15:      8258:   e3a03000    mov r3, #0  ; 0x0

  16:      825c:   e1a00003    mov r0, r3

  17:      8260:   e24bd004    sub sp, fp, #4  ; 0x4

  18:      8264:   e8bd4800    pop {fp, lr}

  19:      8268:   e12fff1e    bx  lr

  20:      826c:   00064b8c    .word   0x00064b8c

  21:  ......

  22:  00013c40 <__libc_open>:

  23:     13c40:   e51fc028    ldr ip, [pc, #-40]  ; 13c20 <___fxstat64+0x50>

  24:     13c44:   e79fc00c    ldr ip, [pc, ip]

  25:     13c48:   e33c0000    teq ip, #0  ; 0x0

  26:     13c4c:   1a000006    bne 13c6c <__libc_open+0x2c>

  27:     13c50:   e1a0c007    mov ip, r7

  28: 13c54: e3a07005 mov r7, #5 ; 0x5   

  #在arch/arm/include/asm/unistd.h中:#define __NR_open  (__NR_SYSCALL_BASE+5)

                    Where __NR_OABI_SYSCALL_BASE is 0

  29:     

13c58: ef000000 svc 0x00000000 #generate soft interrupt

  30:     13c5c:   e1a0700c    mov r7, ip

  31:     13c60:   e3700a01    cmn r0, #4096   ; 0x1000

  32:     13c64:   312fff1e    bxcc    lr

  33:     13c68:   ea0008d4    b   15fc0 <__syscall_error>

  34:  ......


From the code comments above, we can see that the system call number of the system call sys_open is 5. The system call number is stored in register R7. Then the application generates a soft interrupt through svc 0x00000000 and falls into the kernel space.


You may be curious, isn't ARM soft interrupt using SWI? Why is it changed to SVC here? Please see the following paragraph, which is copied from the ARM official website:


SVC


Superuser call. 

grammar


SVC{cond} #immed


in:


cond


    is an optional condition code (see Conditional Execution). 

immed


    is an expression that evaluates to an integer in the range:


        0 to 224–1 (24-bit value) in ARM instructions


        0-255 (8-bit value) in 16-bit Thumb instructions.


usage


The SVC instruction causes an exception. This means that the processor mode is changed to Supervisor mode, the CPSR is saved to the Supervisor mode SPSR, and execution jumps to the SVC vector (see Chapter 6 Handling Processor Exceptions in the Developer's Guide).


The processor ignores immed, but the exception handler obtains it to determine the requested service. 

Note


As part of the ARM assembly language development effort, the SWI instruction has been renamed SVC. In this release of RVCT, the SWI instruction disassembles to SVC, with a comment indicating that this is the old SWI. 

Conditional Tags


This directive does not change the flags. 

Architecture


This ARM instruction is available in all versions of the ARM architecture.


In ARM-based Linux, the exception vector table has been placed at 0xFFFF0000. This process is completed:


start_kernel ---> setup_arch ---> early_trap_init


   1:  void __init early_trap_init(void)

   2:  {

   3:      unsigned long vectors = CONFIG_VECTORS_BASE;  // 就是0xFFFF0000

   4:      extern char __stubs_start[], __stubs_end[];

   5:      extern char __vectors_start[], __vectors_end[];

   6:      extern char __kuser_helper_start[], __kuser_helper_end[];

   7:      int kuser_sz = __kuser_helper_end - __kuser_helper_start;

   8:   

   9:      /*

  10:       * Copy the vectors, stubs and kuser helpers (in entry-armv.S)

  11:       * into the vector page, mapped at 0xffff0000, and ensure these

  12:       * are visible to the instruction stream.

  13:       */

  14:      memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);

  15:      memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

  16:      memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

  17:   

  18:      /*

  19:       * Copy signal return handlers into the vector page, and

  20:       * set sigreturn to be a pointer to these.

  21:       */

  22:      memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,

  23:             sizeof(sigreturn_codes));

  24:   

  25:      flush_icache_range(vectors, vectors + PAGE_SIZE);

  26:      modify_domain(DOMAIN_USER, DOMAIN_CLIENT);

  27:  }

For a detailed explanation of the above function, see:


http://www.cnblogs.com/pengdonglin137/p/3603549.html


To set the location of the exception interrupt vector table to 0xffff0000, you need to modify the 13th bit of register C1 of the coprocessor CP15 and set it to 1. Take the kernel 2.6.30.4 provided by Tq2440 as an example:


 arch/arm/kernel/head.S


   1:      adr    lr, __enable_mmu        @ return (PIC) address

   2:      add    pc, r10, #PROCINFO_INITFUNC

Among them, the value of PROCINFO_INITFUNC is 16, and the value of r10 is the address of __arm920_proc_info:


   1:  __arm920_proc_info:

   2:      .long    0x41009200

   3:      .long    0xff00fff0

   4:      .long   PMD_TYPE_SECT |

   5:          PMD_SECT_BUFFERABLE |

   6:          PMD_SECT_CACHEABLE |

   7:          PMD_BIT4 |

   8:          PMD_SECT_AP_WRITE |

   9:          PMD_SECT_AP_READ

  10:      .long   PMD_TYPE_SECT |

  11:          PMD_BIT4 |

  12:          PMD_SECT_AP_WRITE |

  13:          PMD_SECT_AP_READ

  14:      b    __arm920_setup

  15:      .long    cpu_arch_name

  16:      .long    cpu_elf_name

  17:       ......

  18:      .size    __arm920_proc_info, . - __arm920_proc_info

Take a look at the implementation of __arm920_setup (proc-arm920.S (archarmmm)):


   1:      .type    __arm920_setup, #function

   2:  __arm920_setup:

   3:      mov    r0, #0

   4:      mcr    p15, 0, r0, c7, c7        @ invalidate I,D caches on v4

   5:      mcr    p15, 0, r0, c7, c10, 4        @ drain write buffer on v4

   6:  #ifdef CONFIG_MMU

   7:      mcr    p15, 0, r0, c8, c7        @ invalidate I,D TLBs on v4

   8:  #endif

   9:      adr    r5, arm920_crval

  10: ldmia r5, {r5, r6} @ See the implementation of arm920_crval below. After this sentence is executed, r5 and r6 are: 0x3f3f and 0x3135 respectively.

  11: mrc p15, 0, r0, c1, c0 @ get control register v4 Get the register c1 of coprocessor p15

  12:      

bic r0, r0, r5

  13:      

orr r0, r0, r6 @ We only focus on the 13th bit, here the 13th bit of r0 is set to 1

  14:      

mov pc, lr

  15:      .size    __arm920_setup, . - __arm920_setup

  16:   

  17:      /*

  18:       *  R

  19:       * .RVI ZFRS BLDP WCAM

  20:       * ..11 0001 ..11 0101

  21:       * 

  22:       */

  23:      .type    arm920_crval, #object

  24:  arm920_crval:

  25:      crval    clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130

Let's take a look at the implementation of crval (proc-macros.S (archarmmm)):


   1:      .macro    crval, clear, mmuset, ucset

   2:  #ifdef CONFIG_MMU

   3:      .word    clear

   4:      .word    mmuset

   5:  #else

   6:      .word    clear

   7:      .word    ucset

   8:  #endif

   9:      .endm

After executing mov pc, lr in __arm920_setup, it jumps to the following statement:


   1:  __enable_mmu:

   2:  #ifdef CONFIG_ALIGNMENT_TRAP

   3:      orr    r0, r0, #CR_A

   4:  #else

   5:      bic    r0, r0, #CR_A

   6:  #endif

   7:  #ifdef CONFIG_CPU_DCACHE_DISABLE

   8:      bic    r0, r0, #CR_C

   9:  #endif

  10:  #ifdef CONFIG_CPU_BPREDICT_DISABLE

  11:      bic    r0, r0, #CR_Z

  12:  #endif

  13:  #ifdef CONFIG_CPU_ICACHE_DISABLE

  14:      bic    r0, r0, #CR_I

  15:  #endif

  16:      mov    r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) |

  17:                domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |

  18:                domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) |

  19:                domain_val(DOMAIN_IO, DOMAIN_CLIENT))

  20:      mcr    p15, 0, r5, c3, c0, 0        @ load domain access register

  21:      mcr    p15, 0, r4, c2, c0, 0        @ load page table pointer

  22:      b    __turn_mmu_on

  23:  ENDPROC(__enable_mmu)

Take a look at the implementation of __turn_mmu_on (head.S (archarmkernel)):


   1:      .align    5

   2:  __turn_mmu_on:

   3:      mov    r0, r0

   4:      mcr    p15, 0, r0, c1, c0, 0        @ write control reg

   5:      mrc    p15, 0, r3, c0, c0, 0        @ read id reg

   6: mov r3, r3

   7: mov r3, r3

   8:      mov    pc, r13

   9:  ENDPROC(__turn_mmu_on)

In __turn_mmu_on, the value of register r0 is written to register C1 of the cp15 coprocessor. At this point, the location of the exception interrupt vector table is placed at 0xffff0000.


After talking about the location of the exception vector table, let's take a look at the implementation of soft interrupts.


Interrupt types provided by ARM:

image

ARM's exception handling model:

image

entry-armv.S (archarmkernel)


   1:  .LCvswi:

[1] [2] [3]
Keywords:ARM Reference address:A brief analysis of the implementation of system calls under Linux based on ARM

Previous article:Samsung S3C6410 (ARM1176) platform Android resource acquisition and compilation (RedHat AS5)
Next article:How are the external interrupts of Exynos4412 arranged?

Recommended ReadingLatest update time:2024-11-17 02:24

Make KEIL have both 51 and ARM compilation functions
Install 51 and ARM KEIL separately, they are in different folders, in order to extract the C51 folder. Then the question is, can they be installed in the same folder? Theoretically it works, but I haven't tried it. It's actually very simple, here are the steps: 1. First, move the folder named C51 in the KEIL C51 insta
[Microcontroller]
Transplantation of Real-time Operating System C/OS-II on ARM7
introduction At present, embedded systems are increasingly used in various fields such as home appliances, mobile phones, PDAs, etc., and program design is becoming more and more complex, which requires a general embedded operating system to manage and control them. Embedded system development with an operating syst
[Microcontroller]
Transplantation of Real-time Operating System C/OS-II on ARM7
Understanding and summary of stack pointer SP settings in C language and ARM
What is a stack: Baidu says: A stack is a special linear list that only allows insertion or deletion operations at one end of the list. The end of the table that allows insertion and deletion operations is called the top of the stack. The other end of the table is called the bottom of the stack. The current position
[Microcontroller]
tq2440-arm9 transplantation (problems encountered)
1. Kernel compilation error (different compiler versions used) ARM-Linux-ld: ERROR: drivers/media/video/tq2440/built-in.o is compiled for EABI version 5, whereas drivers/media/video/built-in.o is compiled for version 0 When compiling the kernel, this error occurred. According to the error message, it can be identifie
[Microcontroller]
mini2440 mounts linux folder via nfs
linux 1. Install nfs server sudo apt-get install nfs-kernel-server 2. Modify the configuration file /etc/exports vim /etc/exports Add in the last line /home/stu/nfs *(rw,sync,no_root_squash,no_subtree_check) Where /home/stu/nfs is the directory you want to mount 3. Port Mapping sudo service rpcbind restart
[Microcontroller]
s3c2440 (ARM9) general register addresses
The general register group of 89c51 corresponds to the memory, that is, the address is allocated in the memory, so what about ARM9? Source: http://zhidao.baidu.com/link?url=Nf9NDaITEiA4Gc9q6Y4dP3yt xLJPwBjvRhizxtP0hUu6sQaN qUFqPnS7KEfvfjpIJBlzFKFz q-rBNYXSGx1-va s3c2440a general register address: For example, general
[Microcontroller]
Arm lays the technical foundation for ubiquitous AI
As the innovation foundation of artificial intelligence (AI), many companies are using the general and widely used Arm computing platform. To date, partners have shipped more than 290 billion chips based on the Arm architecture. Today, Arm has supported AI applications in various technology fields, which is wh
[Embedded]
s3c6410 boot Linux process completely from SD card
1. s3c6410 SD boot principle s3c6410 supports Nand Flash local booting of Linux, including kernel, root file system, and bootloader are all written in Nand Flash. This allows independent operation. In many cases, Nand Flash cannot write kernel and Rootfs for some reason. It is slow to download kernel
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
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号