Linux Interrupt Processing Architecture Analysis (1)

Source: Internet
Author: User
Tags prefetch
Exceptions are some things that can interrupt the normal running process of the CPU, such as external interruptions, undefined commands, attempts to modify read-only data, and execution of SWI commands (software interrupt instruction, software interrupt commands. When these events occur, the CPU suspends the current program, processes the exception event first, and then continues executing the interrupted program. In the operating system, exceptions are often used to complete some specific functions. Interruptions also account for a large part. For example, the following situations:
  • When the CPU executes undefined machine commands, the "undefined command exception" is triggered. The operating system can use some custom machine commands, which are implemented in the exception handling function.
  • When the user program tries to read and write data or the executed command is not in the memory, it will also trigger a "Data Access suspension exception" or "command prefetch suspension exception ", in the exception handling function, read the data or commands into the memory and re-execute the interrupted program. This saves memory and allows the operating system to run such programs, they use much larger memory than the actual physical memory.

In the original kernel version, the kernel calls the trap_init and init_irq functions in the start_kernel function (the source code is in init/Main. c) to set exceptions and handling functions. In the kernel version of linux2.6.32.2 (which may have changed in earlier versions), the content of the trap_init function has changed. In trap. C,

void __init trap_init(void)
{
    return;
}

There is also a function in this file,

void __init early_trap_init(void)
{
    unsigned long vectors = CONFIG_VECTORS_BASE;
    extern char __stubs_start[], __stubs_end[];
    extern char __vectors_start[], __vectors_end[];
    extern char __kuser_helper_start[], __kuser_helper_end[];
    int kuser_sz = __kuser_helper_end - __kuser_helper_start;

    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
    memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

     memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
     sizeof(sigreturn_codes));
    memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
     sizeof(syscall_restart_code));

    flush_icache_range(vectors, vectors + PAGE_SIZE);
    modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}

This function is actually used. It can be found in init/mian. C, and trap_init () is called, while early_trap_init () is called in setup_arch (& command_line) function. In Linux/ARCH/ARM/kernel/setup. c

698 void __init setup_arch(char **cmdline_p)
699 {
700 struct tag *tags = (struct tag *)&init_tags;
701 struct machine_desc *mdesc;
702 char *from = default_command_line;

...........
769 early_trap_init();
770 }

In this way, we will understand the specific call process of the trap_init () function. Next, let's take a look at the trap_init () function, specifically the earl_trap_init () function. The earl_tarp_init function (code in arch/ARM/kernel/traps. c) is used to set processing vectors for various exceptions, including interrupt vectors. The so-called "vector" refers to some code placed in a fixed position. When an exception occurs, the CPU will automatically execute these commands at a fixed position. The base address of the CPU exception vector in the ARM architecture can be 0x00000000 or 0xffff0000, which is used by the Linux kernel. The earl_trap_init function copies the exception vector to 0xffff0000. We can see the following two lines of code in this function.

memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

Vectors is equal to 0xffff0000. Address _ vectors_start ~ The code between _ vectors_end is the exception vector, defined in arch/ARM/kernel/entry-armv.S and copied to address 0xffff0000. The exception vector code is very simple. They are just some jump commands. When an exception occurs, the CPU automatically executes these commands and redirects to execute more complex code, such as saving the execution environment of the interrupted program and calling the exception processing function, restore the execution environment of the interrupted program and run it again. These "more complex code" can be found at address _ stubs_start ~ Between _ stubs_end, they are defined in arch/ARM/kernel/entry-armv.S. Copy them to the address 0xffff0000 + 0x200. The code of the exception vector and the exception vector skip execution is written using assembly, which are in the arch/ARM/kernel/entry-armv.S. The code for the exception vector is as follows. "stubs_offset" is used to locate the jump position (the vector is copied to the address 0xffff0000, And the jump destination code is copied to the address 0xffff0000 + 0x200 ).

.equ    stubs_offset, __vectors_start + 0x200 - __stubs_start

. Globl _ vectors_start
_ Vectors_start:
Arm (SWI sys_error0) // reset yes, the CPU will execute this command
Thumb (SVC #0)
Thumb (NOP)
W (B) vector_und + stubs_offset // when an undefined exception occurs, the CPU executes this command.
W (LDR) PC,. lcvswi + stubs_offset // SWI exception
W (B) vector_pabt + stubs_offset // command prefetch aborted
W (B) vector_dabt + stubs_offset // data access is aborted
W (B) vector_addrexcptn + stubs_offset // not used
W (B) vector_irq + stubs_offset // IRQ exception
W (B) vector_fiq + stubs_offset // FIQ exception

    .globl    __vectors_end
__vectors_end:

Among them, vector_und and vector_pabt indicate the code to jump to and execute. Taking vector_und as an example, it is still defined in arch/ARM/kernel/entry-armv.S by vector_stub macro,

vector_stub    und, UND_MODE

. Long _ und_usr @ 0 (usr_26/usr_32) is not fixed in user mode
Command
. Long _ und_invalid @ 1 (fiq_26/fiq_32) executes undefined commands in fiq mode.
. Long _ und_invalid @ 2 (irq_26/irq_32) the undefined command is executed in IRQ mode.
. Long _ und_svc @ 3 (svc_26/svc_32) executes undefined commands in management mode.
. Long _ und_invalid @ 4
. Long _ und_invalid @ 5
. Long _ und_invalid @ 6
. Long _ und_invalid @ 7
. Long _ und_invalid @ 8
. Long _ und_invalid @ 9
. Long _ und_invalid @
. Long _ und_invalid @ B
. Long _ und_invalid @ C
. Long _ und_invalid @ d
. Long _ und_invalid @ E
. Long _ und_invalid @ F

Vector_stub is a macro. It defines a piece of code labeled "vector_und" according to the following parameter "und, und_mode. The vector_stub macro function is to calculate the return address after an exception is processed, save the cause register (such as r0, LR, and spsr), and manage the macro in the management mode, finally, call a next hop branch based on the interrupted working mode. When an exception occurs, the CPU enters a certain working mode based on the exception type, but soon the vector_stub Macro will force the CPU to manage the mode for subsequent processing in the management mode, this method simplifies the program design, so that the working mode before an exception occurs is the user mode or the management mode.
The code indicates the Processing Branch Where an exception occurs when undefined commands are executed in each working mode. For example, _ und_usr indicates that when an undefined command is executed in user mode, the undefined exception will be handled by it; __und_svc indicates that when an undefined command is executed in management mode, the undefined exception will be handled by it. An undefined command exception cannot occur in other working modes; otherwise, "_ und_invalid" is used to handle the error. The ARM architecture CPU uses 4-bit data to represent the working mode. Therefore, there are a total of 16 jump branches. Currently, there are only 7 working modes.

Different jump branches are only slightly different under their portals (for example, the registers for storing interrupted programs), and the subsequent processing is roughly the same, they are calling the corresponding C function, for example, when an undefined command exception occurs, the C function do_undefinstr will be called for processing. Various exception C processing functions can be divided into five categories, which are distributed in different files.
(1) In ARCH/ARM/kernel/traps. c
The undefined C handler function is defined in this file. The total entry function is do_undefinstr.
(2) In ARCH/ARM/MM/fault. c
The memory access-related exception C handler function is defined in this file, such as an exception in Data Access suspension or an exception in command prefetch suspension. The total entry functions are do_dataabort and do_prefetchabort.
(3) In ARCH/ARM/MM/IRQ. c
The interrupt handler function is defined in this file. The total entry function is asm_do_irq, which calls the interrupt handler function registered in other files.
(4) In ARCH/ARM/kernel/call. s
In this file, the SWI exception handler pointer is organized into a table; the SWI instruction machine code bit [] is used as an index. In this way, different SWI exception handling functions can be called through different SWI index commands, such as sys_open and sys_read.
(5) unused exceptions
An error occurred while using FIQ.
The trap_init function builds a framework for handling various exceptions. When an exception occurs, various C processing functions are called. These C functions further break down the exceptions and call more specific processing functions. 2. init_irq function analysis interrupt is also an exception. The reason why it is listed separately is that the interrupt processing is closely related to the specific development board, in addition to some required and shared interruptions (such as system clock interruptions and On-chip peripheral UART interruptions), the driver developer must provide processing functions. The kernel extracts the commonalities of Interrupt Processing and builds an easily expanded interrupt processing system.
The init_irq function (code in arch/ARM/kernel/IRQ. c) is used to initialize the interrupt and processing framework and set the default processing functions for various interruptions. When an interruption occurs, the total interrupt entry function asm_do_irq can call these functions for further processing. From: http://blogold.chinaunix.net/u3/104447/showart_2251010.html

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.