summaryrefslogtreecommitdiff
path: root/doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt')
-rw-r--r--doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt272
1 files changed, 272 insertions, 0 deletions
diff --git a/doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt b/doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt
new file mode 100644
index 0000000..9098d44
--- /dev/null
+++ b/doc/www.independent-software.com_operating-system-development-jumping-to-protected-mode.txt
@@ -0,0 +1,272 @@
+ #[1]Independent Software
+
+ [2][independent-software-logo.svg] [ ]
+ [3]About [4]Philosophy [5]Web Development [6]Portfolio [7]Blog
+
+ [8]osdev [9]asm
+
+ OPERATING SYSTEM DEVELOPMENT
+ JUMPING TO PROTECTED MODE
+
+ -
+
+ Oct 24, 2013
+
+ In the [10]previous section of this tutorial for writing your own toy
+ operating system, we discussed memory and focused on the 21st address
+ line (the "A20 line") that must be enabled before we can have access to
+ the full 4GB of memory, which is a prerequisite to entering protected
+ mode. Now it's time to jump to protected mode.
+
+ In fact, all we've done in the last few articles is prepare for
+ entering protected mode. We've set up a global descriptor table (GDT),
+ an interrupt descriptor table (IDT) and enabled the A20 line. All that
+ remains is actually jumping to protected mode where we'll finally be
+ able to execute 32-bit code so we can focus on our kernel.
+
+ This article is part of a series on toy operating system development.
+
+ [11]View the series index
+ [INS: :INS]
+
+ In the [12]previous section of this tutorial for writing your own toy
+ operating system, we discussed memory and focused on the 21st address
+ line (the "A20 line") that must be enabled before we can have access to
+ the full 4GB of memory, which is a prerequisite to entering protected
+ mode. Now it's time to jump to protected mode.
+
+ In fact, all we've done in the last few articles is prepare for
+ entering protected mode. We've set up a global descriptor table (GDT),
+ an interrupt descriptor table (IDT) and enabled the A20 line. All that
+ remains is actually jumping to protected mode where we'll finally be
+ able to execute 32-bit code so we can focus on our kernel.
+
+ This article is part of a series on toy operating system development.
+
+ [13]View the series index
+
+Control registers
+
+ What we've seen so far while rolling our own first-stage and
+ second-stage boot loaders, is familiar processor registers: AX, BX, CX,
+ DX, segments like CS, DS, ES, SS, the instruction pointer IP and the
+ stack pointer SP. The 80386+ processors actually introduce some new
+ registers what will become important when we switch to 32-bit
+ programming.
+
+ For one thing, existing registers get wider. Where we used to have
+ access to AX (16 bits wide), we will soon have access to EAX (32-bits
+ wide), as well as EBX, ECX and EDX. We'll gain additional segment
+ registers as well (FS and GS). Similarly, the instruction pointer
+ becomes EIP (32 bits again) and so on. That's great, and requires no
+ great deal of explanation.
+
+ However, we gain other registers as well. The Intel 80386 processor
+ comes armed with a set of control registers, and we'll need one of them
+ to switch to protected mode so we might as well talk about it now.
+ These control registers change or control the behavior of the CPU. This
+ includes interrupt control, switching addressing mode, paging and
+ coprocessor control. The new registers are called CR0, CR1, CR2, CR3
+ and CR4.
+
+ The first control register, CR0, has various control flags that modify
+ the basic operation of the processor.
+ Bit Name Full name Description
+ 31 PG Paging If 1, enable paging and use the CR3 register, else disable
+ paging
+ 30 CD Cache disable Globally enables/disable the memory cache
+ 29 NW Not-write through Globally enables/disable write-back caching
+ 18 AM Alignment mask Alignment check enabled if AM set, AC flag (in
+ EFLAGS register) set, and privilege level is 3
+ 16 WP Write protect Determines whether the CPU can write to pages
+ marked read-only
+ 5 NE Numeric error Enable internal x87 floating point error reporting
+ when set, else enables PC style x87 error detection
+ 4 ET Extension type On the 386, it allowed to specify whether the
+ external math coprocessor was an 80287 or 80387
+ 3 TS Task switched Allows saving x87 task context upon a task switch
+ only after x87 instruction used
+ 2 EM Emulation If set, no x87 floating point unit present, if clear,
+ x87 FPU present
+ 1 MP Monitor co-processor Controls interaction of WAIT/FWAIT
+ instructions with TS flag in CR0
+ 0 PE Protected mode enable If 1, system is in protected mode, else
+ system is in real mode
+
+ Some of these bits will become important for us later on, but for now,
+ we're interested in the very first bit: the PE bit. It enables
+ protected mode.
+
+Switching to protected mode
+
+ In order to make the switch to protected mode, all we have to do is
+ enable the PE-bit in the CR0 register, like so:
+.macro mGoProtected
+ mov eax, cr0
+ or eax, 1
+ mov cr0, eax
+.endm
+
+Clearing the prefetch queue
+
+ By setting the PE bit in the CR0 register, we have just switched to
+ protected mode. This means that all instructions are now in 32-bit
+ format. As a result, some of them are encoded differently. Some
+ instructions may take up more bytes in their binary form, some others
+ maybe less, and other still remain unchanged. At any rate, we can't
+ continue executing any more code just yet, because of the prefetch
+ queue.
+
+ You see, CPUs are built to be fast. One of the tricks of the trade that
+ make CPUs ever faster is to have the CPU load a range of instructions
+ from memory to be executed at the same time, rather than just one. This
+ is called prefetching. After all, the CPU in the Intel 80386 processor
+ can read 4 bytes (32 bits) at the same time from memory, and that might
+ well be more than one instruction. For technical reasons, even more
+ might be read and decoded before it's actually executed by the CPU.
+
+ The consequence of this is that the CPU may have read some instructions
+ from memory when it was still in 16-bits mode, decoded them, and is now
+ ready to execute them. They won't work, because the processor is now in
+ protected 32-bits mode!
+
+ Luckily, there is trick to make the processor discard the instructions
+ it has already prefetched, and that trick is jumping. Whenever the
+ processor encounters a jump instruction, any instructions it had read
+ past that instructions become worthless and must be discarded.
+ Consequently, jumping clears the prefetch queue:
+.macro mClearPrefetchQueue
+ jmp clear_prefetch_queue:
+ nop
+ nop
+ clear_prefetch_queue:
+.endm
+
+ There are some nop instructions after the jump, to make doubly sure
+ that the prefetch queue is fully emptied.
+
+Setting up the 80386's registers
+
+ We've talked the talk, now the time has come to walk the walk. Next,
+ we'll set up the memory segments that our future kernel code will use.
+ This is no longer done by putting in memory addresses, but by
+ specifying selector numbers. We'll set all our data segments (ds, es,
+ fs and gs) as well as the stack segment (ss) to use selector 2 from the
+ global descriptor table, which corresponds to the data segment that we
+ had defined in our GDT:
+.macro mSetup386Segments
+ mov ax, 0x10 # Byte offset for selector 2
+ mov ds, ax # (remember, each descriptor is 8 bytes)
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ mov esp, 0x2ffff # Set stack to grown downwards from 0x30000
+.endm
+
+Jumping to the kernel
+
+ Yes! Assuming that our second-stage boot loader had previously loaded
+ our kernel image into memory at linear address 0x20000 (using the same
+ FAT reading at file reading routines we had already developed for the
+ first-stage bootloader), we can now jump to it and start executing it.
+
+ The jump to the kernel must be done with a 32-bit long jump
+ instruction. Here we face a small snag. All the code in our
+ second-stage boot loader is 16-bit code, because that's the way it's
+ compiled. Therefore, we cannot actually specify a 32-bit long jump; it
+ will get compiled as a 16-bit jump. To get around this, we'll encode
+ the long jump instruction ourselves just like a 32-bit assembler would
+ do it.
+
+ Our long jump instruction will jump to linear memory address 0x20000,
+ in the first selector of the GDT (our code segment), which has offset
+ 0x8:
+.macro mJumpToKernel
+ .byte 0x66
+ .byte 0xEA
+ .int 0x20000 # offset
+ .word 0x0008 # selector word
+.endm
+
+ This will transfer control to the kernel code, which we have yet to
+ write. If you're feeling adventurous, why not write a small 32-bit
+ assembly program that places the value 0x41 at linear address 0xb8000?
+ That will show the letter "A" at the top-left corner of the screen and
+ can be executed in protected mode (you can't use the BIOS interrupts to
+ write to the screen anymore).
+
+ Actually, we'll do that in the next part of this tutorial anyway!
+
+Summary
+
+ Whew! It's been quite a trip, but we have now reached protected mode
+ and are ready to write a simple kernel. At least at this point, all of
+ the machine's memory and protected mode features will be at our
+ disposal.
+
+ In this tutorial, we've wrapped up the final bits necessary to enter
+ protected mode:
+ * We've enabled the PE-bit in the CR0 register, thus switching to
+ protected mode
+ * We've cleared the prefetch queue so that no 16-bit instructions
+ remained in the CPU which can no longer be executed
+ * We've setup the registers for use by the 32-bit kernel program
+ * We've executed a long jump to the kernel code
+
+ [14]Continue on to the next part of this guide!
+ [INS: :INS]
+ Please enable JavaScript to view the [15]comments powered by Disqus.
+
+ [independent-software-logo.svg]
+ * 1513 Av. Vladimir Lenine
+ * Maputo, Mozambique
+ * [16]info@independent-software.com
+ * +258 82 304 26 35
+
+Links
+
+ * [17]Web Development
+ * [18]Portfolio
+ * [19]Operating System Development
+
+Social
+
+ * [20]Facebook
+ * [21]Github
+ * [22]LinkedIn
+ * [23]Twitter
+ * [24]Google+
+ * [25]Atom feed
+
+References
+
+ Visible links:
+ 1. http://www.independent-software.com/feed.xml
+ 2. http://www.independent-software.com/
+ 3. http://www.independent-software.com/about-independent-software.html
+ 4. http://www.independent-software.com/philosophy.html
+ 5. http://www.independent-software.com/web-development.html
+ 6. http://www.independent-software.com/portfolio.html
+ 7. http://www.independent-software.com/blog.html
+ 8. http://www.independent-software.com/category/osdev.html
+ 9. http://www.independent-software.com/category/asm.html
+ 10. http://www.independent-software.com/{{%20site.baseurl%20}}{%%20post_url%20/osdev/2013-10-23-operating-system-development-enabling-a20-line%20%}
+ 11. http://www.independent-software.com/operating-system-development.html
+ 12. http://www.independent-software.com/operating-system-development-enabling-a20-line.html
+ 13. http://www.independent-software.com/operating-system-development.html
+ 14. http://www.independent-software.com/operating-system-development-first-and-second-stage-bootloaders.html
+ 15. https://disqus.com/?ref_noscript
+ 16. mailto:info@independent-software.com
+ 17. http://www.independent-software.com/web-development.html
+ 18. http://www.independent-software.com/portfolio.html
+ 19. http://www.independent-software.com/operating-system-development.html
+ 20. https://www.facebook.com/Independent-Software-295360497495620/
+ 21. https://github.com/henck
+ 22. https://www.linkedin.com/company/independent-software-mozambique-
+ 23. https://twitter.com/IndependentSw
+ 24. https://google.com/+Independent-software
+ 25. http://www.independent-software.com/feed.xml
+
+ Hidden links:
+ 27. http://www.independent-software.com/operating-system-development-jumping-to-protected-mode.html