Writing a Simple Operating System — from Scratch

(Jeff_L) #1

CHAPTER 4. ENTERING 32-BIT PROTECTED MODE 37


Like I said before, the actual switchover is fairly straight forward to code, but it is
important to understand the significance of the steps involved.
The first thing we have to do is disable interrupts using thecli(clear interrupt)
instruction, which means the CPU will simply ignore any future interrupts that may
happen, at least until interrupts are later enabled. This is very important, because, like
segment based addressing, interrupt handling is implemtented completely differently in
protected mode than in real mode, making the current IVT that BIOS set up at the start
of memory completely meaningless; and even if the CPU could map interrupt signals to
their correct BIOS routines (e.g. when the user pressed a key, store its value in a buffer),
the BIOS routines would be executing 16-bit code, which will have no concept of the
32-bit segments we defined in our GDT and so will ulimately crash the CPU by having
segment register values that assume the 16-bit real mode segmenting scheme.
The next step is to tell the CPU about the GDT that we just prepared --- with great
pain. We use a single instruction to do this, to which we pass the GDT descriptor:


lgdt [gdt_descriptor]

Now that all is in-place, we make the actual switch over, by setting the first bit of a
special CPU control register,cr0. Now, we cannot set that bit directly on the register,
so we must load it into a general purpose register, set the bit, then store it back into
cr0. Similarly to how we used theandinstruction in Section XXX to exclude bits from
a value, we can use theorinstruction to include certain bits into a value (i.e. without
disturbing any other bits that, for some important reason, may have been set already in
the control register) [?].


mov eax , cr0 ; To make the switch to protected mode , we set
or eax , 0x1 ; the first bit of CR0 , a control register
mov cr0 , eax ; Update the control register

Aftercr0has been updated, the CPU is in 32-bit protected mode [?].
That last statement is not entirely true, since modern processors use a technique
calledpipelining, that allows them to process different stages of an instruction’s execution
in parallel (and I am talking about single CPUs as opposed to parallel CPUs), and
therefore in less time. For example, each instruction might befetchedfrom memory,
decodedinto microcode instructions,executed, then perhaps the result isstoredback to
memory; and since these stages are semi-independent, they could all be done within the
same CPU cycle but within different circuitry (e.g. the previous instruction could be
decodedwhilst the next isfetched) [?].
We do not normally need to worry about CPU internals such as pipelining when
programming the CPU, but switching CPU modes is a special case, since there is a risk
that the CPU may process some stages of an instruction’s execution in the wrong mode.
So what we need to do, immediately after instructing the CPU to switch mode, is to
force the CPU to finish any jobs in its pipeline, so that we can be confident that all
future instructions will be executed in the correct mode.
Now, pipelining works very well when the CPU knows about the next few instructions
that will be coming over the horizon, since it can pre-fetch them, but it doesn’t like
instructions such asjmporcall, because until those instructions have been executed
fully the CPU can have no idea about the instructions that will follow them, especially if
we use afarjump or call, which means that we jump to another segment. So immediately
after instructing the CPU to switch mode, we can issue a far jump, which will force the

Free download pdf