After calling SystemTable->BootServices->ExitBootServices() and SystemTable->RuntimeServices->SetVirtualAddressMap(), I copied my kernel image to a fixed address and tried to load my own GDT instead of using the UEFI one (which has 70-ish entries).
However, whenever I attempt to load a data segment register (like mov %ax, %ds) or run lretq to load CS, a triple fault is thrown. After a few days' trial-and-error I found this was directly related to the limit value in GDTR. If its set to any value < 23, a triple fault occurs on segment register load. I'm fine with keeping a large GDT but still really curious about the reason, because I don't recall such a restriction on GDT size anywhere. Can anyone explain this to me? Thanks.
By the way, it's a 64 bit kernel and UEFI starts it in protected long mode.
Code: Select all
struct gdtr {
uint16_t size;
uint64_t addr;
} __attribute__((packed));
jos_gdt[1] = create_descriptor(0, 0xfffff, GDT_CODE_PL0);
jos_gdt[2] = create_descriptor(0, 0xfffff, GDT_DATA_PL0);
struct gdtr gdt;
gdt.addr = (uint64_t)jos_gdt;
// Triple fault if size < 23
gdt.size = 24;