pcmattman wrote:Code: Select all
00048819962e[CPU0 ] fetch_raw_descriptor: GDT: index (f) 1 > limit (0)
00048819962e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00048819962e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
Looks like your GDT limit is zero, according to the processor. I'd be checking your GDTR. The fact that the index it's trying to find is 0xF is also probably indicative of a problem...
Well, I rode that the two low-order bytes are the limit and the 4 high-higher bytes are the base so I just created an uint64 and put (limit + base << 16) in it before LGDTing it. Is this wrong ?
You may also want to set your data segments after you load the GDT and before you long jump to load CS, instead of after the load of CS.
Done. New inline asm chunk :
Code: Select all
__asm__ volatile ("lgdt (%0);\
mov $16, %%ax;\
mov %%ax, %%ds;\
mov %%ax, %%es;\
mov %%ax, %%fs;\
mov %%ax, %%gs;\
mov %%ax, %%ss;\
ljmp $8, $bp;\
bp:\
xchg %%bx, %%bx;\
mov $24, %%ax;\
ltr %%ax"
:
: "r" (&gdtr)
: "%ax", "%bx"
);
I now encounter exactly the same crash, but with the data segment (which is in fact reassuring since I made it pretty much the same way as the code segment) :
Code: Select all
00048819962e[CPU0 ] fetch_raw_descriptor: GDT: index (17) 2 > limit (0)
gerryg400 wrote:Should your gdt and tss really be local variables ?
Well, they probably shouldn't, but I won't ever be modifying them. My initial plan was "Go in long mode first and care about those things later, no use creating pmode structures with care if it's to replace them with long mode one a few cycles later". Apparently, GRUB's GDT could be not enough to achieve that goal, so I quickly hacked another one which should last just long enough to make the long mode switch before being nuked. That's why I set ESP0 = 0 in the TSS, by the way : I really, *really* don't plan to use it. It's just because I need one, apparently, according to the GDT tutorial.
I'm no expert in inline assembler but shouldn't that be
Aaah, I'd love that if it worked... However note that the GDTR is 48-bit data. So except using some black magic which I don't know about, I think I can't just load it in a 32-bit register and LGDT it.
I hence tried the following :
1/Get some uint64 (gdtr) around.
2/Fill it with the appropriate value (which is base << 16 + limit if I understood the paragraph about the two low-order bytes being a limit and the four high-order bytes being the base)
Code: Select all
gdtr = (uint32_t) gdt;
gdtr <<= 16;
gdtr += 32;
3/Put its address in a register (see the definition of %0 in the inline assembly macro
4/Run lgdt [register]'s att assembly equivalent. (which is lgdt (%0), I think)
Is that wrong ?