CPU Initialization

Looking at the fourth tutorial video on youtube (4. Initialization) I noticed that an x86 CPU can be forced working on protected mode by setting a bit "directly":
mov ebx, cr0
or ebx, 1
mov cr0, ebx

However this was done without disabling interrupts and the gdt was loaded after entering the rotected mode.
Is this a good way of doing things? Why on osdev http://wiki.osdev.org/Protected_Mode they disable interrupts first?
cli ; disable interrupts
lgdt [gdtr] ; load GDT register with start address of Global Descriptor Table
mov eax, cr0
or eax, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0)
mov cr0, eax

What can happend if i set the PE bit without disabling interrupts?

Comments

  • Hi!

    The sample code for most of the tutorials starts with "cli" immediately after "_Kernel_Start". This means that interrupts are disabled throughout the initialisation process - right up until `sti` is executed (which happens in the 8. Interrupts tutorial). So interrupts are disabled as per the OSDev example.

    Disabling interrupts is a bit misleading; all that is really disabled are device interrupts - that is, interrupts which originate from things attached to the processor (e.g. PS2, Timers, etc.) rather than the processor itself. These types of interrupts are also called IRQs. Disabling interrupts does not prevent processor exception interrupts such as divide by zero or general protection faults.

    Why bother disabling them? Well:
    1. If one of the device interrupts is enabled, e.g. Keyboard, then if the user presses are key the processor will try to handle an IRQ for the key press. Another example is if a timer device is enabled and its IRQ is enabled then a periodic (or possibly one-shot) interrupt could occur during initialisation.
    2. Your initialisation can be at one of three stages:
    a. Just started - still holding the bootloader setup. In which case, the IRQ is going to invoke the bootloader (or potentially the BIOS). If neither had configured an interrupt handler in the IVDT/IDT, then the system is going to hit a double fault, which is an unrecoverable situation at this stage.
    b. Started but not changed IVT/IDT (Interrupt Vectors Table / Interrupt Descriptors Table depending on current processor mode) - still holding bootloader of BIOS setup. Again, an IRQ (e.g. keyboard press) will cause the handler to be invoked and your OS initialisation to be interrupted. Depending on the BIOS or bootloader, this may cause the system to restart or any number of other fatal possibilities.
    c. Started and changed IVT/IDT - In which case your initialisation gets interrupted and one of your own methods executes. Unless you want to wrap every interrupt handler in an "is the system ready" check (not a good idea) then your interrupt handler is probably going to be start using uninitialised memory (because your initialisation process hadn't finished yet).

    So disabling interrupts during initialisation is necessary to avoid the initialisation process accidentally being interrupted or diverted. With a lot of knowledge and planning, you can work out the earliest stage at which interrupts can be safely enabled.

    Most online sample code disables interrupts as a first step because they are showing you just a short snippet of the full system. So They add "cli" just to make the reader hasn't accidentally left them enabled.

    "GDT then PMode switch" or "PMode switch then GDT" is dependent upon whether you trust the pre-configured (by bootloader) GDT. The tutorial code provided does trust it so loads GDT afterwards. The recommendation in general is to load the GDT beforehand, do PMode switch then do the far-jump (demo'd at the end of the GDT init code) to force a reload of the CS register.

    Hope this answers your questions! Cheers,
    Ed
  • Fantastic explanation, thank you very much!
This discussion has been closed.