-
Notifications
You must be signed in to change notification settings - Fork 229
Open
Description
The code in GlobalDescriptorTable::GlobalDescriptorTable() fails to reload the segment registers after creating a GDT and loading it with lgdt. As a result, the code expects that GRUB's values for the code and data segment selectors are the same as the OS. While the multiboot spec guarantees that the segment registers are loaded with flat descriptors with a maximum limit, the actual selector values can't be assumed to be specific values. In function GlobalDescriptorTable::GlobalDescriptorTable() in gdt.cpp change:
asm volatile("lgdt (%0)": :"p" (((uint8_t *) i)+2));
to:
asm volatile(
"lgdt %0\n"
"mov %2, %%ds\n" /* Set segments to the data selector */
"mov %2, %%es\n"
"mov %2, %%fs\n"
"mov %2, %%gs\n"
"mov %2, %%ss\n"
"push %1\n" /* Use Far Return to set CS:EIP */
"push $1f\n"
"retf\n"
"1:\n" /* Far return returns to this location */
:
: "m" (*(((uint8_t *) i)+2)),
"r"(CodeSegmentSelector()),
"r"(DataSegmentSelector())
: "memory"
);
Without this change, running QEMU with the -cdrom option may work but with -kernel it may not. QEMU isn't buggy in this regard but WYOOS is.
Metadata
Metadata
Assignees
Labels
No labels