The essence of Linux Kernel Mode and User Mode - Linux implementation on ARM Architecture

As an operating system, Linux Kernel is different from general user programs, the so-called kernel mode and user mode. Programs running in Kernel mode can access all memory and can handle interrupts; programs in user mode can only access limited memory and cannot handle interrupts directly. So who decides these differences between kernel mode and user mode? In the final analysis, all programs are instructions of the CPU. The same instruction can sometimes do something and sometimes cannot. This is determined by the mode of the CPU when the instruction is executed. In short, when executing the Kernel instruction, the CPU is in privileged mode and can access all memory; when executing the user program instruction, the CPU is in user mode, and reading and writing memory is restricted; and when an Interrupt occurs, it is necessary to operate Hardware, so the CPU will switch from the original working Mode to the privileged mode to execute the Interrupt handler. The following will explain in detail how the Linux operating system runs on the ARM architecture.

 

  1. ARMProcessor Mode

ARM has the following 7 Processor Modes. The current mode is determined by bit4:0 of ​​the Current Program Status Register (CPSR):

  • User: User Mode User Mode

  • FIQ : Fast Interrupt Request

  • IRQ: Normal Interrupt Request

  • SVC: Supervisor Mode Supervisor Mode

  • Abort: Abort Mode Abort Mode

  • Undefined: Undefined Mode Undefined Mode

  • System: system mode

Among them, User Mode is a restricted mode, and the other 6 are privileged modes (Privilege Mode).

 

These modes can be switched between each other, and the switching methods can be attributed to the following two:

 

The first: the switching is done by the CPU itself hardware

The CPU itself actively switches the mode because some kind of "accident" occurs when executing the instruction, and this "accident" is Exception. Once an Exception occurs, the CPU will immediately switch to the mode corresponding to this Exception to process the Exception. All Exceptions are handled in Privilege Mode. There are 6 kinds of Exceptions in ARM CPU. The conditions for them to occur and the CPU mode they enter after they occur are as follows:

 

 

Exception

Triggering conditions

enter CPU mode

Reset

The Reset pin of the CPU is Assert (When the CPU Power is on, the Reset pin will be Assert)

SVC

Undefined Instruction:

Attempt to execute an unrecognized instruction

Undefined

Software Interrupt (SWI)

Execute command SWI

SVC

Prefetch Abort

Failed to get command

Abort

Data Abort

Failed to get data

Abort

IRQ

A normal interrupt occurs, the IRQ pin of the CPU is asserted

IRQ

FIQ

A fast interrupt occurs, the FIQ pin of the CPU is asserted

FIQ

 

Note that both IRQ and FIQ exist in Exception and CPU modes, but their meanings are different. The former refers to an Exception event, and the latter refers to a mode of CPU operation.

 

The second: the program modifies the CPSR

Some instructions can modify the CPSR, and executing these instructions in the program can switch the mode of the CPU. However, not all of these modes can be switched by modifying the CPSR. For example, in User Mode, the CPSR cannot be modified to switch to other Modes. Usually, when returning from an Exception, the CPSR should be modified, so as to resume the execution of the CPU Mode when the Exception occurred.

 

  1. Kernel mode and User mode of Linux

 

     Linux Kernel工作在Privilege mode下,它需要处理所有在privilege mode下完成的工作。如IRQFIQ Exception发生时,进入相应的Privilege Mode,由Kernel来处理相应的IRQ, FIQ事件。也就是说,Kernel 对应CPU6Privilege Mode。正是因为privilege mode可以对系统资源“特权“的访问,所以kernel能够控制所有的软硬件资源,因而被称为”操作系统“。

 

 

     User mode运行在CPUUser processor mode下,所以在访问memory等方面都有限制,用户的各种Application都运行在User Mode下。User Mode下的程序想要访问只有Privilege Mode才能访问的资源就必须使用系统调用(System Call),进入Kernel Mode来处理。从User Mode进入Priviledge mode的唯一方式是swi指令,这条指令执行会触发Software Interrupt Exception, 从而进入SVC模式。所以System call的实质就是通过swi指令进入Kernel Mode。在kernel中处理完毕后,kernel会将CPU切回到User Mode继续执行,同时将调用结果返回到User Mode

 

下表说明了CPU Mode与Linux Mode之间的对应关系:

 

User

FIQ

IRQ

Supervisor

Abort

Undefined

System

Kernel Mode

 

User Mode

 

 

 

 

 

 

 

  1. CPU Mode切换的场合在Linux中的实现

如 前所述,所有CPU privilege模式下的工作都对应于OS的Kernel mode,那么所谓Linux Kernel mode和User mode之间的切换映射到CPU层面来说就是CPU的User mode怎样切换到其他6种mode,每种privilege mode又怎样切换到User mode的。同时,6中Privilege Mode之间当Exception发生时也会切换。下面我们将对照Linux kernel 2.6.33的代码来逐一分析每种Exception发生时Linux Kernel是怎样处理的。

 

在ARM Architecture中,Exception发生时指令将从固定的地址开始执行。所以必须在这些地址上放置正确的代码来处理相应的Exception。这些固定的地址也称向量,由CP15 Reg1中的V bit控制,可以在虚拟内存的底部或顶部。注意是虚拟内存,也就是说这些向量的固定地址是虚拟地址,是要经过MMU转换的。各Exception对应的向量地址(虚拟地址)如下:

 

 

Low Vector

High Vector

Reset

0

0xFFFF0000

Undefined Instruction:

0x04

0xFFFF0004

Software Interrupt (SWI)

0x08

0xFFFF0008

Prefetch Abort

0x0C

0xFFFF000C

Data Abort

0x10

0xFFFF0010

IRQ

0x18

0xFFFF0018

FIQ

0x1C

0xFFFF001C

 

在Linux kernel中向量位于高地址,由CONFIG_VECTORS_BASE控制,Default为0xFFFF0000,在__arm926_setup中将CP15 control register 1的V bit置为1(High Vector)。向量表在源代码里位于entry-armv.S中,从__vector_start开始,在FIQ, IRQ等被enable前,必须要copy到0xFFFF0000开始的高地址。Copy的时点在start_kernel ()->setup_arch()->early_trap_init()中。在setup_arch()之后的local_irq_enable()才是真正clear CPSR的I-bit,至此,IRQ才Enable了。

下面逐一讲述各Exception Handler的实现。

  1. Reset

CPU Power on后即触发Reset Exception。Reset发生后,CPU进入SVC Mode, PC被设置为0,即从内存地址0开始执行代码。这是系统启动的开端。对应arm Linux中,arch/arm/kernel/head.S中的“__HEAD"开始即是系统执行的Kernel的第一行代码(2.6.33中是设置CPSR,disable FIQ, IRQ)。用objdump vmlinux也可以看到此行代码是Kernel的第一条指令。详细Linux启动的过程在”Linux Kernel的启动过程“一文中阐述。

在向量表中Reset Exception的向量处是执行swi SYS_ERROR0,这条指令将触发SWI Exception,在vector_swi中通过判断参数,最终将执行到die(),系统停止运行。也就是说,Linux在运行过程中发生Reset Exception,将被认为是系统错误而停止。

  1. 发生IRQ

IRQ Exception发生时将从__vector_irq开始执行。这部分代码稍显晦涩。源代码中__vector_irq这个符号是由__vector_stub这个宏产生的。__vector_stub这个宏实现了IRQ和Abort Exception的共用部分,主要是保存SPSR,然后根据发生Exception时 的Program Mode跳转到相应的处理分支上。处理分支的table是紧跟在_vector_stub之后,可以看到每一种Program mode下发生IRQ对应于table中的一个entry。SVC下发生IRQ的时候就进入__irq_svc,User Mode下发生IRQ的时候就进入__irq_user。关于__irq_usr和__irq_svc中具体是怎样处理IRQ的,详见“Linux中IRQ的处理“一文。

  1. 发生Prefetch Abort

与IRQ一样,发生Prefrech Abort时将跳转到__pabt_usr和_pabt_svc的分支上处理。

  1. 发生Data Abort

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326951014&siteId=291194637