I am new to kernel and I'm currently re-reading xv6's source code.
I find that sth I used to assume right seems very confusing now...
Here is the code snippet:
---------------------------------------------------------------
lgdt gdtdesc
movl %cr0, %eax
orl $CR0_PE, %eax
movl %eax, %cr0
# Complete the transition to 32-bit protected mode by using a long jmp
# to reload %cs and %eip. The segment descriptors are set up with no
# translation, so that the mapping is still the identity mapping.
ljmp $8, $start32
---------------------------------------------------------------
Before enabling protected mode, cs=0, we work in real mode, cs*16+ip works just fine.
What makes me confused is that, how to make sure the 1st instruction getting executed after enabling protected mode is the ljmp above? AFAIK now, when protected mode is on, processor will use hidden/invisible content of cs register to perform the logical address -> linear address translation -- but the hidden content seems never set before...
Currently I can only assume that the hidden content is 'SOMEHOW' set by 'SOMEONE' so that when protected mode is on, hidden content for cs gives us BASE=0 and LIMIT=0xFFFFF.
Can someone please explain me the exact detail make the 'ljmp $8, $start32' the 1st instruction after enabling protected mode?
Doubts on the first instruction after enabling ProtectedMode
Doubts on the first instruction after enabling ProtectedMode
- Attachments
-
[The extension s has been deactivated and can no longer be displayed.]
-
- Member
- Posts: 5575
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Doubts on the first instruction after enabling Protected
The hidden content is called the segment descriptor cache. The CPU always uses the descriptor cache for the segment base and limit, even in real mode.c2hpxq wrote:Currently I can only assume that the hidden content is 'SOMEHOW' set by 'SOMEONE' so that when protected mode is on, hidden content for cs gives us BASE=0 and LIMIT=0xFFFFF.
In real mode, whenever you load a segment register, that value is shifted left four bits and put into BASE. Since CS was loaded with 0 in real mode, BASE is 0, so there's no problem reaching the next instruction after the MOV to CR0.
In real mode, nothing can modify LIMIT. When the CPU powers on or resets, LIMIT is 0xFFFF. (Firmware might temporarily switch to protected mode, but it will ensure LIMIT is at least 0xFFFF before switching back to real mode to boot the OS.)
-
- Member
- Posts: 797
- Joined: Fri Aug 26, 2016 1:41 pm
- Libera.chat IRC: mpetch
Re: Doubts on the first instruction after enabling Protected
When you are in real mode and enable protected mode by changing bit 0 of CR0 to 1 - you are actually in 16-bit protected mode. One other problem though is that any processor that prefetched instructions as 16-bit real mode that came after the update of CR0 were not decoded as 16-bit protected mode. Any kind of unconditional jump (like an LJMP) will clear the instruction prefetch queue and force the instructions after the LJMP to be reloaded by the processor. That is usually why it is a good idea to place the LJMP after the change to CR0.c2hpxq wrote: Can someone please explain me the exact detail make the 'ljmp $8, $start32' the 1st instruction after enabling protected mode?
The LJMP is the last step in the process of getting to 32-bit protected mode. When CS is loaded with a 32-bit code selector that changes the processor from 16-bit protected mode to 32-bit protected mode.