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: ARM's exception handling model: entry-armv.S (archarmkernel) 1: .LCvswi:
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
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- BQ4050 cannot be unlocked using BQStudio
- [New Year's flavor competition] + Zongzi brown sugar with fish every year, Guizhou's strong special New Year flavor
- The difference between brushed motor and brushless motor
- Share a copy of the altium library file for zynq7000
- Live: Fluke experts talk about Fluke vibration monitoring solutions and product lines
- 【STM32WB55 Evaluation】_06_Temperature and humidity data upload experiment
- The May Day holiday is coming soon. How are you guys planning your holiday?
- EEWORLD University Hall----Application of Signal Processing in Power Engineering
- rt-thread studio 1.1.2 starts to support Arteli chips.
- 【GD32E231 DIY Contest】3. Light up a row of digital tubes