Without the GDT, nobody will be able to tell you. However, segment 0x10 refers to index 2, and 0x30 refers to index 6 (you just have to divide by eight).zap8600 wrote:I believe that it is pointing to the 16-bit segment. It should instead point to 0x30, which I believe is the 64-bit segment.
You are loading the TR with 0x2B, which refers to index 5. Your problem is that segment 5 is not initialized correctly, You set the limit (one byte too high, because the limit for some reason is one less than the size of the segment, but that is immaterial here) and the base, but never the segment type. This is why you should read the CPU manuals which detail the structure of the thing.zap8600 wrote:If this is the case though, I believe the problem should be fixed by replacing the 5 with 7.
In 64-bit mode, the TSS is a long segment, i.e. it uses two consecutive GDT entries for the whole base pointer. I have the GDT declared as just an array of 64-bit numbers, and therefore I can just do this initialization:
Code: Select all
static void init_gdt(uint64_t *gdt, const struct tss* tss)
{
uint64_t tssp = (uint64_t)tss;
gdt[KCODE_DESC] = 0x00af9a000000ffff;
gdt[KDATA_DESC] = 0x00af92000000ffff;
gdt[UDATA_DESC] = 0x00aff2000000ffff;
gdt[UCODE_DESC] = 0x00affa000000ffff;
gdt[TSS_DESC] = (tssp << 16) & 0xffffff0000 | (tssp << 32) & 0xff00000000000000 | sizeof (struct tss) - 1 | (uint64_t)0x89 << 40;
gdt[TSSU_DESC] = tssp >> 32;
}