1

In a typical simple bootloader writing for x86, we have the following code to load the GDT and perform a far jump (note that CS is 0x0 before executing the following code):

lgdt gdtdesc
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp $0x8, $protcseg

.code32                                             # Assemble for 32-bit mode
protcseg:

However, just after lgdt CS is null, pointing to a null descriptor in GDT. So :

1.How on earth can the CPU fetch the correct instruction just after GDT is loaded by lgdt?

2.DPL of the code segment to far-jump to is usually 0, does the CPU perform privilege check when doing the far jump?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

1 Answers1

1

Until the far jump loads the internal CS base/limit/stuff from a GDT entry, you're not using any GDT entry at all. It's not really even protected mode.

Unlike enabling paging (where instruction fetch for the next instruction treats CS:EIP as virtual in the next instruction after writing CR0), segment stuff doesn't happen until after a writing a segment register causes the CPU to actually read from the GDT.

The CS base address isn't changed by LGDT, and you're still at maximum privilege level with operand-size = address-size = 16, so code-fetch of the ljmp instruction just happens. (Assuming execution of this snippet started in real or unreal mode.) Being in protected mode affects the meaning of updating CS to 8, but doesn't affect fetching and running the instruction that does that.

I don't know the formal details of whether it counts as CPL=0 or if it's a special case, or what would happen if your first far jump was to a call gate. If you want more than that, have a look at https://wiki.osdev.org/GDT_Tutorial and/or Intel or AMD's manuals, or maybe someone else will answer this question.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847