I did not pay attention to this problem at first, just through the trap door feel very mealy, why not directly call Write_char in Level 3 user code, today's own writing program want to call the code snippet, only to find the big problem. I wrote a process similar to Write_char, with the following code:
Dividing_line:push%GSPUSHL%EBXPUSHL%ecxmovl $1,%ecx/* Output 1 spaces ' */movl $SCRN _SEL,%EBXMOVW%bx,%gs1:movl scr_loc,% EBXSHL $1,%ebxmovb $32,%gs: (%EBX)/* "Space ASCII code */SHR $1,%EBXINCL%ebxcmpl $2000,%EBXJB2FMOVL $0,%ebx2:movl%ebx,scr_ Locloop 1bpopl%ecxpopl%ebxpop%gsret
Its function is to output a space on the screen. It's almost the same as Write_char, except I've specified the characters to output, not by AX. Another difference is that I'm calling Dividing_line by call instead of being called by a trap gate like Write_char.
The result is that the program is hung and cannot be run.
Later analysis, the reason is very simple. I do not call Write_char directly in the Task1. The reason for both is the same: the two lines of code.
MOVL $SCRN _SEL,%EBXMOVW%bx,%gs
In the source code scrn_sel= 0x18 is a GDT display data segment selector, don't care what he is the data segment, anyway, he is the data segment is right, this data segment descriptor Dpl=0, belongs to the high privilege level, but we now use the privilege Level 3 code to call this process, Then this process is counted as a member of the 3-level program, that is, his privileged level is also 3, cpl=3, although scrn_sel= 0x18 rpl=0, but CPL is not enough level, this load scrn_sel= 0x18 request will be rejected by the processor. When the processor loads the selector into the segment register, it will compare the CPL, selector RPL of the current operating program, and the DPL that is directed to the descriptor, unless the CPL and RPL are numerically less than DPL, which is a higher privilege level. Otherwise, this load selector behavior will be intercepted by the processor and a protection exception is generated.
back to my program, so as long as this load 0x18 this selector behavior exists, this process of invocation will inevitably fail, because 0x18 this selector point to the data segment descriptor DPL superelevation. As a matter of fact, in the Level 3 program directly call Write_char or Dividing_line, will fail, have no access to this data section, there is no intention.
This is why to call the Write_char through the trap gate, the processor rules can only be transferred to the high privileged code segment through the trap gate, not to the low privileged level of the code snippet, which means that I transfer from level 3 user code to kernel level 0 code this is justified. Note, however, that level 3 code can indeed be transferred to level 0 code through trap gates, but only if the gate descriptor of the trap gate is dpl=3. Otherwise, the user program does not have access to the trap door at all. Well, let's assume trap gate descriptor dpl=3, the target code inside the trap Gate descriptor selector point to a kernel level 0 code.
So when the level 3 program to load Trap Gate descriptor, completely feasible, because cpl=3, we then use rpl=3 selector to access trap door, trap door dpl=3, so that can access the trap door completely. Then the target selector part of the trap door points to the level 0 code, it doesn't matter, we can go through the trap door completely, the processor will we do! This is the process that should be done. Low-level programs access low-level trap doors, low-level traps have high-privileged code snippet selector, which can be transferred through the trap door into the high-privileged kernel code. This provides convenience for some system calls.
Finally, let's get rid of the two lines of code that cause the problem, can we call it normal? The answer is yes, since the two lines to go, then the function of the process is wasted, not as simple as writing a point, such as:
EXAMPLE:PUSHL%EAXMOVL $0x250,%eaxpop%eaxret
This is simple enough, in the Level 3 user code Call example can be called, there is no output hint so we can confirm by Bochs debugging, the result is a successful call, the execution process successfully entered this example code. This is a normal near call, nothing special. About Trap Gate Privilege level we're going to talk about this.
I'm done.
This article is from the "mirage1993" blog, make sure to keep this source http://mirage1993.blog.51cto.com/2709744/1576602
Why does the Linux0.00 kernel have to set the 0x80 trap gate itself to invoke the Write_char process?