Fully analyzes the jump rules between privileged-level and privileged-level code segments in chapter 3 of "writing an operating system by yourself"

Source: Internet
Author: User

"Write the operating system yourself" read Sense http://blog.csdn.net/zgh1988/article/details/7059936

Comprehensive analysis of the first chapter of "self-writing Operating System" http://blog.csdn.net/zgh1988/article/details/7060032

Comprehensive Analysis of the "self-writing Operating System" Chapter 2 http://blog.csdn.net/zgh1988/article/details/7062065

Comprehensive Analysis of the "hands-on writing Operating System" Chapter 3 1 http://blog.csdn.net/zgh1988/article/details/7098981

Comprehensive Analysis of "writing an operating system by yourself"-"Real mode-protection mode-real mode"
Http://write.blog.csdn.net/postedit/7256254

Comprehensive Analysis of the "hands-on writing the Operating System" -- stack segment of the work mode http://blog.csdn.net/zgh1988/article/details/7256254

 

Here I will use pmtest4.asm and pmtest5.asm to describe my understanding of the privileged level and the redirection between different privileged-level codes.

1. privileged level

2. consistent and non-consistent code segments

3. DPL, RPL, and CPL represent the meaning, location, and relationship between them.

4. access rules for data segments

5. transfer between different privileged code segments

6. Stack

7. Use pmtest5.asm to describe the jump process with different privileges

I. privileged level

Under the segment mechanism of ia32, the privileged level has a total of four privileged levels, ranging from high to low, which are 0, 1, 2, and 3. A smaller number indicates a larger privileged level.

Shows the privilege level:

 

The core code and data will be stored in a privileged level. The processor will use this mechanism to prevent low-privilege tasks from accessing high-privilege segments without being permitted.

2. consistent and inconsistent code segments

To ensure system security, ensure that the kernel is separated from the user program. To ensure kernel security, you must not be disturbed by the user. But sometimes, user programs also need to access part of the data in the kernel. What should we do?

Therefore, the operating system divides the segments in the kernelShared code segmentAndNon-shared code segments.

WhereConsistent code segmentThe code that is shared by the operating system and can be directly accessed by low-privilege users.

Consistent code segmentRestrictions:

1) code segments with high privileges are not allowed to access code segments with low privileges: Kernel States are not allowed to call code in user State.

2) code segments with low privilege level can access code segments with high privilege level, but the current privilege level does not change. That is, the user State can access the kernel state code, but the user State is still the user State.

 

Inconsistent code segment: System Code protected by the operating system to avoid low-privilege access is non-shared code.

Inconsistent code segmentRestrictions:

1) only allow access at the same privileged level

2) access between different levels is absolutely prohibited, that is, the user State cannot access the kernel state, and the kernel state does not access the user State.

 

Access rules for consistent and non-consistent segments:

III. The meanings of CPL, DPL, and RPL, respectively, and the locations where they are stored and Their Relationships

CPL(Current privilege level) is the privileged level of the currently executed program or task. It is stored in 0th-bit and 1st-bit CS and SS. In general, CPL is equal to the privileged level of the code segment. In case of consistent code segments, consistent code segments can be accessed by code with the same or lower privilege level. CPL is not changed when the processor accesses a consistent code segment that is different from the CPL privilege level.

DPL(Descriptor privilege level): DPL indicates the privileged level of a segment or gate. It is stored in the DPL field of the segment descriptor or gate descriptor. When the current code segment tries to access a segment or door, DPL will compare with CPL and RPL of the segment or door Selection Sub-, and DPL will be treated differently according to the segment or door type, the following describes various types of segments or portals.

Data Segment:DPL specifies the minimum privilege level for access to this segment. For example, if the DPL of a data segment is 1, only programs running on CPL 0 or 1 have the right to access it.

Inconsistent code segment (without calling the door ):DPL specifies the privilege level to access this segment. For example, if the privilege level of a non-consistent code segment is 0, only programs with CPL 0 can access it.

Call door:DPL specifies the minimum privilege level for the currently executed program or task to access this call gate (which is consistent with the data segment rules ).

Consistent code segment and non-consistent code segment accessed through the call door:DPL specifies the highest privilege level to access this segment. For example, if the DPL of a consistent code segment is 2, programs with CPL 0 and 1 cannot access this segment.

RPL(Requested privilege level): RPL is represented by selecting the 0th and 1st sub-bits. The processor checks RPL and CPL to check whether an access request is valid.

4. access rules for data segments

DPL in the Data Segment specifies the lowest privilege level for access to this segment. Therefore, for data access, as long as CPL and RPL are smaller than the dpl of the accessed data segment, cpl <= DPL and RPL <= DPL.

5. transfer between different privileged code segments

The following four types of transfer can be achieved using JMP or call commands:

(1) The target operand contains the segment Selection Sub of the target code segment.

(2) The target operand points to a call gate descriptor that contains the child selected by the target code segment.

(3) The target operand points to a TSS that contains the child of the target code segment.

(4) The target operand points to a task door, which points to a TSS containing the child of the target code segment.

The four methods can be seen as two categories, one is direct transfer through JMP and call (the first one), and the other is indirect transfer through a descriptor (the second, 2, 3, 4 ).

1. Direct transfer through JMP or call

2. Transfer by calling the door (1) method of calling the door

First, we will introduce the gate descriptor:

 

The gate descriptor contains the selection child of the target code segment.

The following uses pmtest4.asm as an example to describe how to use the gate descriptor.

Segment descriptor of the target code segment

Label_desc_code_dest: descriptor 0, SegCodeDestLen-1, da_c + da_32

Select child for the target code segment

Selectorcodedest equ label_desc_code_dest-label_gdt

Call gate Descriptor

Label_call_gate_test: gate selectorcodedest, 0, 0, da_1_cgate + da_dpl0

Call door Selection Sub-

Selectorcallgatetest equ label_call_gate_test-label_gdt

Use

Call selectorcallgatetest: 0

(2) rules for determining the unique permission level when using the call door for transfer

Suppose we want to transfer code A to code B, and use a call gate g, that is, the target selection in the call gate g points to the segment of code B. In fact, this problem mainly involves these elements: CPL, RPL, DPL of code B (record as dpl_ B), call the DPL of the gate g (record as dpl_g ).

When calling the door for use, the rules for the special permission level check are as follows:

 

That is to say, by calling the door and call command, the transfer from the low-privilege level to the high-privilege level can be achieved, regardless of whether the target code segment is consistent or inconsistent.

By calling the door and JMP command, if the target code segment is consistent, the transfer from the low-privilege level to the high-privilege level can be realized. If the target code segment is inconsistent, only transfer at the same privilege level can be implemented.

6. Stack 1, long jump/call, and short jump/call

If a call or jump command is performed between time periods rather than within a segment, it is called a "long" (far JMP/call). Otherwise, if it is in a segment, it is "short" (near JMP/call ).

 

So what are the differences between Long and Short JMP or call?

For JMP, the results are only different. For short jump, the CIDR blocks are different.

For call, it is more complicated, because the call command affects the stack. The effects of long call and short call on the stack are different.

 

Next we will discuss the impact of short calls on the stack. When the call command is executed, the EIP of the next command is pressed to the stack. When the RET command is executed, this EIP will pop up from the stack,

As shown in:

This is a short call.

 

Next we will discuss the impact of long calls on the stack. When the call command is executed, the caller's CS and EIP will be pushed to the stack. When the RET command is executed, this eip and CS will be popped up from the stack, as shown in:

2. Impact of transition with privilege-level transformation on Stack

Stack segments are different under different privileged levels, so each task may be transferred between four privileged levels at most. Therefore, each task requires four stacks. However, we only have one SS and one esp. in case of stack switching, where do we obtain the SS and esp of the remaining stacks?

To solve this problem, a Data Structure TSS (Task-state stack) is required ),

When the stack is switched, the SS and ESP in the inner layer are obtained from here. For example, we are currently in ring3, and when it is transferred to ring1, the stack is automatically switched to the position specified by SS1 and esp1. Because the new stack is obtained from the TSS only when the switch from the outer layer to the inner layer (low-privilege level to high-privilege level), there is no stack information of ring3 In the TSS.

 

Let's take a look at the entire transfer process?

 

Stack segment changes before and after call execution:

(1) Select the SS and ESP to be switched from the TSS according to the DPL (New CPL) of the target code segment

(2) read the new SS and esp from the TSS. In this process, if an SS, ESP, or TSS boundary error is found, the TSS exception will be invalid.

(3) Check the SS descriptor. If an error occurs, the # ts exception is also generated.

(4) temporarily Save the value of the current SS and ESP

(5) Load new SS and ESP

(6) press the stored SS and ESP values into the new stack.

(7) Copy parameters from the caller stack to the called Stack (New stack). The number of copy parameters is determined by Param count in the call gate.

(8) If Param count is zero, the parameter is not copied.

(9) apply the current CS and EIP to the stack

(10) load the new CS and EIP specified in the call door and start the caller process.

 

Stack segment changes before and after RET execution:

(1) Check the RPL In the stored CS to determine whether to change the privilege level when returning the data.

(2) load the Cs and EIP on the caller's stack (the code segment descriptor and selection subtype and privilege level check will be performed at this time)

(3) If the RET command contains parameters, the value of ESP is added to skip the parameter, and ESP points to the stored caller SS and ESP. Note: The RET parameter must correspond to the value of param count in the call door.

(4) load the SS and ESP, switch to the caller stack, and the SS and esp of the caller are discarded. The SS descriptor, ESP, and SS segment descriptor will be verified here

(5) If the RET command contains parameters, add the ESP value to skip the parameter (which is already in the caller's stack)

(6) Check the values of DS, es, FS, and Gs. If the DPL of a register pointing to a segment is smaller than CPL (this rule is not suitable for consistent code segments ), then an empty descriptor is loaded into this register.

 

To sum up, the process of using the call door is actually divided into two parts, one is from the low-privilege level to the high-privilege level, through the call door and call command; the other part is implemented through RET commands from the high-privilege level to the low-privilege level.

 

7. Use pmtest5.asm to describe the jump process with different privileges

 

; ========================================================== =; Pmtest5.asm; Compilation Method: NASM pmtest5.asm-O pmtest5.com; ========================================================== = % include "PM. INC "; constants, macros, and some descriptions of or1_100hjmplabel_begin [section. gdt]; gdt; Segment Base Address, segment boundary, attribute label_gdt: descriptor 0, 0, 0; empty descriptor label_desc_normal: descriptor 0, 0 ffffh, da_drw; normal descriptor: descriptor 0, segcode32len-1, da_c + da_32; inconsistent code segment, 32label_des C_code16: descriptor 0, 0 ffffh, da_c; inconsistent code segment, sequence: descriptor 0, segcodedestlen-1, da_c + da_32; inconsistent code segment, sequence: descriptor 0, segcodering3len-1, da_c + da_32 + da_dpl3; inconsistent code segment, rule: descriptor 0, datalen-1, da_drw; rule: descriptor 0, topofstack, da_drwa + da_32; stack, 32-bit label_desc_stack3: descriptor 0, topofstack3, da_drwa + DA _ 32 + da_dpl3; stack, 32-Bit Memory: descriptor 0, tsslen-1, da_1_tss; Memory: descriptor 0b8000h, 0 ffffh, da_drw + da_dpl3; display address; target Selection Sub-, offset, dcount, attribute limit: gate selectorcodedest, 0, 0, da_1_cgate + da_dpl3; gdt ends gdtlenequ $-label_gdt; gdt length limit-1; gdt boundary dd0; gdt base address; gdt Select Sub-selectornormalequlabel_desc_normal-label_gdtselectorcode32equlabel_desc _ Code32-extract-transform-label_gdt + extract-label_gdtselectorvideoequlabel_desc_video-label_gdtselec Torcallgatetestequlabel_call_gate_test-label_gdt + sa_rpl3; end of [section. gdt] [section. data1]; Data Segment align32 [bits32] label_data: spvalueinrealmodedw0; string pmmessage: DB "in protect mode now. ^-^ ", 0; after entering protection mode, this string offsetpmmessageequpmmessage-$ strtest: DB" success ", 0 offsetstrtestequstrtest-$ datalenequ $-label_data; end of [section. data1]; Global stack segment [section. GS] align32 [bits32] label _ STACK: Times 512 db 0 topofstackequ $-label_stack-1; end of [section. GS]; stack segment ring3 [section. s3] align32 [bits32] label_stack3: Times 512 dB 0topofstack3equ $-label_stack3-1; end of [section. s3]; TSS parts [section. tss] align32 [bits32] label_tss: dd0; backddtopofstack; level 0 stack ddselectorstack; dd0; Level 1 stack dd0; dd0; 2 Level stack dd0; dd0; cr3dd0; eipdd0; priority; eaxdd0; ecxdd0; edxdd0; ebxdd0; espdd0; priority; edidd0; esdd0; priority; ssdd0; dsdd0; priority; ldtdw0; debug trap mark DW $-label_tss + 2; I/O bitmap base address db0ffh; I/O bitmap end sign tsslenequ $-label_tss; TSS ^ ^ ^ [section. s16] [bits16] label_begin: movax, csmovds, axmoves, axmovss, axmovs P, 0100 hmov [forward + 3], axmov [spvalueinrealmode], SP; initialize 16-bit code snippet descriptor movax, csmovzxeax, axshleax, 4 addeax, delimiter [label_desc_code16 + 2], axshreax, 16 movbyte [forward + 4], almovbyte [label_desc_code16 + 7], Ah; initialize 32-bit code segment descriptor xoreax, eaxmovax, csshleax, 4 addeax, struct [forward + 2], axshreax, 16 movbyte [label_desc_code32 + 4], Al Movbyte [label_desc_code32 + 7], Ah; initialize the code segment descriptor xoreax, eaxmovax, csshleax, 4 addeax, descriptor [label_desc_code_dest + 2], axshreax, 16 movbyte [forward + 4], almovbyte [forward + 7], Ah; initialize data segment descriptor xoreax, eaxmovax, dsshleax, 4 addeax, label_datamovword [label_desc_data + 2], axshreax, 16 movbyte [label_desc_data + 4], almovbyte [label_desc_data + 7], Ah; Initialize stack segment descriptor xoreax, eaxmovax, dsshleax, 4 addeax, label_stackmovword [increment + 2], axshreax, 16 movbyte [increment + 4], almovbyte [label_desc_stack + 7], Ah; initialize stack segment descriptor (ring3) xoreax, eaxmovax, dsshleax, 4 addeax, label_stack3movword [forward + 2], axshreax, 16 movbyte [forward + 4], almovbyte [forward + 7], ah; initialize ring3 descriptor xoreax, eaxmovax, dsshleax, 4 addeax, Label_code_ring3movword [kernel + 2], axshreax, 16 movbyte [kernel + 4], almovbyte [kernel + 7], Ah; initialize TSS descriptor xoreax, eaxmovax, dsshleax, 4 addeax, label_tssmovword [records + 2], axshreax, 16 movbyte [records + 4], almovbyte [records + 7], Ah; xoreax, eaxmovax, dsshleax, 4 addeax, label_gdt; eax <-gdt base address movdword [gdtp Tr + 2], eax; [gdtptr + 2] <-gdt base address; load gdtrlgdt [gdtptr]; close the CLI; open the address line a20inal, 92 horal, 20170010bout92h, Al; prepare to switch to protection mode moveax, cr0oreax, 1movcr0, eax; truly enter protection mode jmpdword selectorcode32: 0; execute this sentence will load selectorcode32 into CS, and jump to code32selector: 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;; label_real_entry:; jump from the protection mode to the actual mode. Here, movax, csmovds, axmoves, axmovss, and axm Ovsp, [spvalueinrealmode] Inal, 92 h; incluandal, 11111101b; ┣ disable A20 address line out92h, Al; ┛ STI; interrupt movax, 4c00h; interrupt int21h; disconnect back to DOS; end of [section. s16] [section. s32]; 32-bit code segment. jump from the real mode. [bits32] segments: movax, selectordatamovds, ax; Data Segment Selection Sub-movax, selectorvideomovgs, ax; video segment Selection Sub-movax, selectorstackmovss, ax; stack segment Selection Sub-movesp, topofstack; the following is a string movah, 0ch; 0000: Black Bottom 1100: Red xoresi, esixoredi, edimovesi, offs. Etpmmessage; source data offset movedi, (80*10 + 0) * 2; destination data offset. The screen contains 10th rows and 0th columns. Cld.1: lodsbtestal, aljz.2mov [GS: EDI], axaddedi, 2jmp. 1.2:; displayed calldispreturn; load tssmovax, selectortssltrax; Switch the stack when a privileged level change occurs in the task, and the pointer of the inner stack is stored in the TSS of the current task, therefore, you must set the task status segment register tr. Pushselectorstack3pushtopofstack3pushselectorcodering3push0retf; ring0-> ring3, historical transfer! The number '3' is printed '.; When dispreturn: pusheaxpushebxmoveax, edimovbl, 160 divblandeax, 0 ffhinceaxmovbl, 160 mulblmovedi, done; dispreturn ends when segcode32lenequ $-label_seg_code32; end of [section. s32] [section. sdest]; call the target segment [bits32] label_seg_code_dest: movax, selectorvideomovgs, ax; select the video segment Sub-(Purpose) movedi, (80*12 + 0) * 2; screen 12th rows, 0th columns. Movah, 0ch; 0000: Black Bottom 1100: red letter moval, 'C' mov [GS: EDI], axretfsegcodedestlenequ $-label_seg_code_dest; end of [section. sdest]; 16-bit code segment. jump from a 32-bit code segment and jump out to the actual mode [section. s16code] align32 [bits16] kernel:; mode: movax, selectornormalmovds, axmoves, axmovfs, axmovgs, axmovss, axmoveax, cr0andal, cosine, cosine: jmp0; the segment address will be set to the correct value at the beginning of the program code16lenequ $-label _ Seg_code16; end of [section. s16code]; codering3 [section. ring3] align32 [bits32] label_code_ring3: movax, selectorvideomovgs, ax; video segment Selection Sub-(destination) movedi, (80*14 + 0) x 2; screen 14th rows, 0th columns. Movah, 0ch; 0000: Black Bottom 1100: red letter moval, '3' mov [GS: EDI], axcallselectorcallgatetest: 0; test the call door (privileged level change ), the letter 'C' will be printed '. JMP $ segcodering3lenequ $-label_code_ring3; end of [section. ring3]

 

83-117 initialize the task status stack segment (TSS)

292-300 use retf to jump from ring0 --> ring3, that is, jump from high-privilege level to low-privilege level to label_code_ring3.

380-380 through the call door, the jump from ring3 --> ring0 is completed, that is, the jump from low-privilege level to high-privilege level, and the jump to label_seg_code_dest

336-336 uses retf to jump from ring0 --> ring3, that is, jump from high-privilege level to low-privilege level, and jump to 379.

 

So far, we have achieved two transfers from the high-privileged level to the low-privileged level, and from the low-privileged level to the high-privileged level, finally, the program stops in Low-privilege code.

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.