A brief analysis of stack switching based on Jos 80x86
This problem has been plagued for a long time, found still a little careless, source-stack initialization is not how to understand.
First of all, it is important to understand the mechanisms of segmentation and paging protection.
Existing segments, after pagination, paging is optional, see if the Register CR0 open PE bit (page enable. It has been opened in the Boot.s of the Jos System)
This paper analyzes the stack from three aspects.
0. GDT Global segment Addressing description table
1. Initialization of the stack.
2. Switch the user stack to the kernel stack
3. Switch the kernel stack to the user stack
0. GDT Global segment Addressing description table
You can see the NO. 0 paragraph this time is not allowed to access, gd_kt right shift three bits into (0x8 >> 3 = 1), the first segment is the kernel code snippet. Readable executable. The second one is GD_KD right three bits (0x10 >> 3 = 2) The second paragraph. is the kernel data segment.
The third Gd_ut moves right three bits (0x18 >> 3 = 3) The third segment is the user code snippet.
Fourth Gd_ud move right three bits (0x20 >> 3 = 4) The fourth segment is the user data segment.
The following TSS segments are not very relevant to our theme, only useful when the task is switched.
After seeing this, I don't have to worry about people pretending that "code and data are separate," I don't understand.
Paper Tiger!
1. Initialization of the stack.
First the boot system starts to run when the boot. s stage, the stack is set immediately before it is opened. How to do it?
First, the AX register XOR 0. Then assign the value of the AX register to the DS es SS register.
Initially, the data segment, the extra segment, the stack segment, all point to the No. 0 segment. There's no paging mechanism at this time.
Segment addressing address = = Segment:offset = = (segment << 4 bits) + offset to get the physical address directly
And here is the No. 0 paragraph of the choice! Comrade,... In this "primitive wilderness," the address you use is a physical address.
Then the paging mechanism is turned on immediately,
The LGDT command immediately loads the GDT Global Segment Description Table we described earlier.
Turning on the paging mechanism, we also entered the protection mode.
Then the various segments DS CS in the bootloader stage point to the kernel data segment that the PROT_MODE_DSEG 0x10 points to
The important thing to say three times,
The stack segment and data segment in Jos Point to the same segment,
The stack segment and data segment in Jos Point to the same segment,
The stack segment and data segment in Jos Point to the same segment,
: )
To later initialize the CPU, it is also the SS point to GD_KD
OK, here's the initialization of the stack even if it's clear (at least I feel very good about myself haha ha)
2. Switch the user stack to the kernel stack.
There are a variety of ways to switch, we focus on a trap Gate triggered by the switch is good (the rest of the call gate, Interrupt Gate,task Gate) can go to see Zhao Jiong 0.11 linux Source code analysis that book, The introduction to 80x86 is very detailed and can also be read in Intel's manual ...
Focus on the * (int *) 0xDeadBeef = 0 just fine, the others can be ignored, and the topic of our section is irrelevant, we are concerned about the switch of the stack.
Because here try to write to an illegal address, then direct page fault, there are meters there!
Because of the triggered exception, the CPU will help us to switch the stack segment directly (note that many other registers do not automatically switch, but CS SS will!). )
Accreditations, let's test it.
The following is the state of the various registers that happened just before this pit-father's instructions were executed
General registers do not need to pay attention to, focus on the CS SS DS es fs GD eflags is good
Let's look at the comparison chart below. Triggers the comparison before and after page fault.
You will find that the CS SS has changed the other DS ES FS GS has not changed, and this time eflags if the logo is not, the interruption is blocked.
Conclusion: When triggering an anomaly, the CPU automatically switches between the code snippet and the stack segment register, and the data segment is not automatically switched so that we need to manually switch the DS in the assembly code. When the DS is switched on, it completes the so-called switch from user state to kernel state.
3. Switch the kernel state to the user state (the case of user exception stack is not discussed here).
Really switch places here. Switch from kernel stack to normal user stack. is essentially a reverse process of the previous user state to the kernel state.
The order of the Register pops is completely opposite ...
Here the TF pointer to the struct TRAPFRAME set to the top of the stack pointer, very clever to restore the various registers of various values.
The stack switch occurs until the last Iret because the return address is no longer within the kernel code snippet.
This is a comparison of the registers before and after switching:
After switching, the eflags immediately has an IF, allowing interrupt invocation.
A brief analysis of stack switching based on Jos 80x86