Process 0 Moves from Privilege Level 0 to 3 and Becomes a

Một phần của tài liệu The art of linux kernel design (Trang 96 - 100)

2. Device Initialization and Process 0 Activation 45

2.14 Process 0 Moves from Privilege Level 0 to 3 and Becomes a

Linux OS requires that all processes should be built by an existing process in privilege level 3, with the exception of process 0. In Linux 0.11, the code and data of process 0 are written in the kernel of the OS. It is in privilege level 0; at this time, strictly speaking, the process 0 is not a real process. In order to comply with the rules, before process 0 creates process 1, process 0 must be moved from privilege level 0 to 3. The specific method is to call the function move_to_user_mode, imitating the interrupt return action, to move the privilege level of process 0 from 0 to 3.

ROM BIOS and VGA

Kernel

Disable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area (IDT)

0 47 255

floppy_interrupt

do_fd_request blk_dev [7]

blk_dev [7]

floppy_interrupt do_fd_request

Motherboard

8259A

After setting disk Before setting disk Step 1:

hook floppy request service program do_fd_request to the second item of blk_dev [7]

(#define MAJOR_NR 2 in floppy.c)

Step 2:

hook floppy interrupt service program floppy_interrupt to the 0x26 item of IDT

Step 3: reset floppy interrupt request mask bit, allow floppy disk controller to send interrupt request signal

Kernel code area Kernel data area

0 47(IDT)255

Figure 2.27 Initialize the floppy disk.

The code is as follows:

EFLAGS

0 0 0 0 0 0 0 0 0 0 IDV PI VI FA

CV MR

F 0N T

OI PL

OFD F I

FT FS

FZ F

0 0 0 0 0 0 0 0 0 0 IDV PI VI FA

CV MR

F 0N T

OI PL

OFD F I

FT FS

FZ F

0 AF 0 PF 1 CF

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

0 AF 0 PF 1 CF

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Disable interrupt

Enable interrupt

Before enabling interrupt After enabling interrupt

EFLAGS

1

0

Figure 2.28 Enable the interrupt.

//Code path: init/main.c:

void main(void) {

……

move_to_user_mode();

……

}

//Code path: include/system.h: //See 1.3.4

#define move_to_user_mode() \ //Imitate push, the order is ss, esp, eflags, cs, eip __asm__(“movl%%esp,%%eax\n\t” \

“pushl $0x17\n\t” \ //Push ss, 0x17 is 10111 in binary system(Privilege //level 3, ldt, data segment)

“pushl%%eax\n\t” \ //Push esp

“pushfl\n\t” \ //Push eflags

“pushl $0x0f\n\t” \ //Push cs, 0x0f is 1111 in binary system(Privilege level //3, ldt, Code segment)

“pushl $1f\n\t” \ //Push eip

“iret\n” \ //return, move from the privilege level 0 to 3

“1:\tmovl $0x17,%%eax\n\t” \ //The following codes make ds, es, fs, gs and ss //have the same value

“movw%%ax,%%ds\n\t” \

“movw%%ax,%%es\n\t” \

“movw%%ax,%%fs\n\t” \

“movw%%ax,%%gs” \ :::“ax”)

One way to change the privilege level in IA-32 is through interruption, as introduced in Chapter 1. When an interrupt request is received, the CPU can interrupt the current program; cs:eip switches to perform the corresponding interrupt service routine. When finished, perform iret to return to the interrupted program to continue.

During this period, the CPU hardware does two things: to protect and restore the environment and to change the privilege level.

We can see from the code performance that interruption is just like function calls.

They can jump from a code that is being executed to another section of the code and then return to the original code to execute after finishing the execution of the new code.

In order to make sure that the process could return to the original code accurately, you need to push CS and EIP to save the next line of code (protect environment). When fin- ished executing the called function or interrupt service routine, pop CS and EIP (restore environment). Thus, the CPU can perform the called function or interrupt program accu- rately. The EFlags and other important registers also need to be protected.

The difference between interruption and function call is that the function call is designed by a programmer; the compiler can compile in advance the protection and the restoration code. While the interruption is unpredictable, they cannot be compiled in advance. Hence, the protection and restoration environment of the interruption have to be performed by the hardware. Therefore, the command int instruction will cause the hardware to complete the push of SS, ESP, EFlags, CS, and EIP. Similarly, when executing the command iret, the hardware will pop them to the corresponding register.

According to the settings of dpl, when the CPU responds to the interruption, it can change the privilege level. In function sched_init(), set_system_gate (0x80,&system_call) is to set the interrupt int 0x80 move from privilege level 3 to 0. When the process of privi- lege level 3 do the system call int 0x80, CPU will flip to privilege level 0. Similarly, the com- mand iret could change the privilege level from 0 to 3.

The function move_to_user_mode is based on this principle, using iret to change the privilege level from 0 to 3.

So far, process 0 is in privilege level 0; the stack does not have the values of these five registers: ss, esp, eflags, cs and eip. In order to use the command iret, the designer pushes value of these registers manually, which is similar to the command int. When performing the command iret, the CPU automatically pops this 5 value to the register and turns to privilege level 3, executing the code in privilege level 3.

In order to change to privilege level 3, not only should the push order be correct, but the privilege level of SS and CS must also be right. Note that the value of SS in the stack is 0x17, which is 00010111 in the binary system; the last two bits represent 3, the user privi- lege level. Then, the sixth bit is 1, which means the segment descriptor is obtained from the LDT; the 10 of 4–5 bits means obtaining the stack segment descriptor from the third item of the LDT.

When executing the command iret, the hardware would pop the 5 value from the stack to SS, ESP, EFlags, CS, and EIP in order. The pop order is the same as the usual inter- ruption return; also, the effect of the return is the same.

When the system finished executing the function move_to_user_mode(), equivalent to an interruption return, the privilege level of process 0 changes from 0 to 3, which means process 0 becomes a real process.

This page intentionally left blank This page intentionally left blank

Một phần của tài liệu The art of linux kernel design (Trang 96 - 100)

Tải bản đầy đủ (PDF)

(524 trang)