I've been getting a triple fault when trying to set the SS register after loading my GDT. I was getting a bunch of very strange GP faults when working on interrupts, and realized I hadn't set the segment registers after creating and loading my GDT. When I tried to set them, it works for all of the registers except the SS register. The OS is 64-bit, already in long mode, and loaded via UEFI. I'm running it on a VirtualBox machine. I don't want to flood the post with too much code, but here's my GDT loading function
Code: Select all
GDTCodeOrDataEntry* initializeGDT(PhysicalMemoryLayout* physMemLayout) {
GDTCodeOrDataEntry* gdt = (GDTCodeOrDataEntry*) AllocatePage(physMemLayout);
gdt[0] = (GDTCodeOrDataEntry) { 0, 0, 0, 0, 0, 0 }; //Null entry
// Initialize table with "default" entries
for(int i = 1; i < GDT_BASE_ENTRIES; i++) {
gdt[i] = basicGDTEntry();
}
// Define kernel/userspace code segments
// Note: Default entries work for both data segments, as priviledge levels
// are ignored in 64-bit mode data segments
gdt[GDT_KERNEL_CODE_ARRAY_INDEX].accessByte |= ACCESS_EXECUTABLE_FLAG;
gdt[GDT_KERNEL_CODE_ARRAY_INDEX].limitPartTwoAndFlags |= LONG_MODE_CODE_FLAG;
gdt[GDT_USER_CODE_ARRAY_INDEX].accessByte |= ACCESS_EXECUTABLE_FLAG | ACCESS_USERSPACE_FLAG;
gdt[GDT_USER_CODE_ARRAY_INDEX].limitPartTwoAndFlags |= LONG_MODE_CODE_FLAG;
// Set up GDTR data
GDTRegister gdtr;
gdtr.limit = GDT_BASE_ENTRIES * sizeof(GDTCodeOrDataEntry) - 1;
gdtr.baseAddress = (UInt64) gdt;
// Load GDT and jump to new kernel code 'segment'
asm volatile goto (
"lgdt %0\n\t"
"mov %2,%%rax\n\t"
"mov %%rax,%%ds\n\t"
"mov %%rax,%%es\n\t"
"mov %%rax,%%fs\n\t"
"mov %%rax,%%gs\n\t"
"mov %%rax,%%ss\n\t"
"pushq %1\n\t"
"pushq $%l3\n\t"
"retfq\n\t"
: /* No output */
: "m"(gdtr), "r"(GDT_KERNEL_CODE_SELECTOR_INDEX), "r"(GDT_KERNEL_DATA_SELECTOR_INDEX)
: "rax", "memory", "cc"
: finish_lgdt
);
finish_lgdt:
return gdt;
}
Code: Select all
rax=0000000000000010 rbx=0000000000062020 rcx=0000000000000010 rdx=0000000000000008
rsi=0000000000041028 rdi=0000000000000061 r8 =000000000000007d r9 =00000000dfa082ce
r10=0000000000000078 r11=00000000dfa082ce r12=00000000de71f698 r13=0000000000000109
r14=0000000000000000 r15=0000000000000000 iopl=0 nv up di pl nz na pe nc
rip=0000000000402257 rsp=00000000df237830 rbp=00000000df237870
cs=0038 ds=0010 es=0010 fs=0010 gs=0010 ss=0030 rflags=00000002
%0000000000402257 8e d0 mov ss, eax
Code: Select all
0008 CodeEO Bas=00000000 Lim=000fffff DPL=0 P NA AVL=0 L=1
0010 DataRO Bas=00000000 Lim=000fffff DPL=0 P A AVL=0 L=0
0018 CodeEO Bas=00000000 Lim=000fffff DPL=3 P NA AVL=0 L=1
0020 DataRO Bas=00000000 Lim=000fffff DPL=0 P NA AVL=0 L=0