Page 1 of 2

GDT in C

Posted: Thu Jan 29, 2004 8:59 am
by mr. x
Hi.
I'm trying to setup GDT in my C kernel, but there's something wrong.
The bootloader sets up a GDT for me to use, but I want to set one up in my kernel.
Someone said I can get the address of the GDT with LGDT, how?
And, when will I have to access the GDT in my kernel, do I have to access it when I create a process?

Code: Select all

//////////////////////////////////////////////////////////////////////////
// GDT
typedef struct {
   uint16 low_limit;
   uint16 low_base;
   uint8 middle_base;
   uint8 settings;
   uint8 high_limit:4;
   uint8 attributes:3;
   uint8 granularity:1;
   uint8 high_base;
} x86_gdt;


//////////////////////////////////////////////////////////////////////////
// GDT Descriptor
typedef struct {
   uint16 limit;
   x86_gdt* base;
} __attribute__ ((packed)) gdtr;


gdtr GDTR;
x86_gdt GDT[20] = {0};
 
int InitializeMemManager() {
   // Null segment
   GDT[0].low_limit =      0x0;
   GDT[0].low_base =      0x0;
   GDT[0].middle_base =   0x0;
   GDT[0].settings =      0x0;
   GDT[0].high_limit =      0x0;
   GDT[0].attributes =      0x0;
   GDT[0].granularity =   0x0;
   GDT[0].high_base =      0x0;
 
 
   // Code segment
   GDT[1].low_limit =      0xFFFF;
   GDT[1].low_base =      0x0;
   GDT[1].middle_base =   0x0;
   GDT[1].settings =      0x9A; // Non-conforming, PL0
   GDT[1].high_limit =      0xF;
   GDT[1].attributes =      0x4;
   GDT[1].granularity =   0x0;
   GDT[1].high_base =      0x0;
 
   // Data segment
   GDT[2].low_limit =      0xFFFF;
   GDT[2].low_base =      0x0;
   GDT[2].middle_base =   0x0;
   GDT[2].settings =      0x92; // Write access, expand down
   GDT[2].high_limit =      0xF;
   GDT[2].attributes =      0x4;
   GDT[2].granularity =   0x0;
   GDT[2].high_base =      0x0;
 
 
   GDTR.limit = 256 * (sizeof(x86_gdt) - 1);
   GDTR.base = GDT;
 
   gdtr* GDTRPtr = &GDTR;
 
   kprintf("GDT @ 0x%X\n", GDTRPtr);
 
   outb(0x70, inb(0x70) | 0x80); // Disable NMI
 
   asm volatile("xor %%ax, %%ax \n\t" \
             "mov %%ax, %%ds \n\t" \
             "lgdt (%0) ": :"p" (GDTRPtr));
 
   WriteCR0(ReadCR0() | 0x80000000);
 
   outb(0x70, inb(0x70) & 0x7F); // Enable NMI
   return 0;
}


Re:GDT in C

Posted: Thu Jan 29, 2004 10:14 am
by mr. x
Oh, BTW:
I get a General Protection Fault with that code. ;)

Re:GDT in C

Posted: Thu Jan 29, 2004 10:20 am
by Candy
mr. x wrote: Oh, BTW:
I get a General Protection Fault with that code. ;)
Where does this code run? You do not set the G bit, so if you're using an address >1M it should crash.

Re:GDT in C

Posted: Thu Jan 29, 2004 11:21 am
by df
why are you enabling paging straight after loading GDT? is your paging setup properly in CR3?

Re:GDT in C

Posted: Thu Jan 29, 2004 11:22 am
by mr. x
I tested to set the G bit (granularity) and it didn't help...
high 32 in GDT[1] is 110011111001101000000000

Re:GDT in C

Posted: Thu Jan 29, 2004 11:26 am
by mr. x
df wrote: why are you enabling paging straight after loading GDT? is your paging setup properly in CR3?
Woops, I had commented out the line which setup paging... well it doesn't work anyway.

Re:GDT in C

Posted: Thu Jan 29, 2004 1:45 pm
by Pype.Clicker
1. did you made sure the gdtr struct was 6 bytes and the descriptor strcut was 8 ?
2. are you aware that changes performed on GDTR will have no effect until segment registers are re-loaded ?
3. why do you declare the limit as 256*sizeof(descriptor) if you allocate only 20 of them ??
4. what the **** does the PG bit comes here ?

Re:GDT in C

Posted: Thu Jan 29, 2004 2:51 pm
by mr. x
1. did you made sure the gdtr struct was 6 bytes and the descriptor strcut was 8 ?
yes.
2. are you aware that changes performed on GDTR will have no effect until segment registers are re-loaded ?
yes.
3. why do you declare the limit as 256*sizeof(descriptor) if you allocate only 20 of them ??
I've changed it to 20 now.
4. what the **** does the PG bit comes here ?
It's removed now.


And it still doesn't work. :|

Code: Select all

00005196106i[CMOS ] read of index port 0x70. returning 0xff
00005196131e[CPU  ] seg = DS
00005196131e[CPU  ] seg->selector.value = 0000
00005196131e[CPU  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

Re:GDT in C

Posted: Thu Jan 29, 2004 3:36 pm
by nullify
1. Make sure you "__attribute__ ((packed))" your x86_gdt structure.
2. If you know that you must reload the segment registers after you load the GDTR register, why isn't that in your code?
3. Is there a reason you must temporarily disable NMI before loading the GDTR?
4. What is the purpose of the XOR and MOV instructions you put just prior to the LGDT instruction?
5. The following:

Code: Select all

GDTR.limit = 256 * (sizeof(x86_gdt) - 1);
should probably be:

Code: Select all

GDTR.limit = (256 * sizeof(x86_gdt)) - 1;

Re:GDT in C

Posted: Thu Jan 29, 2004 4:07 pm
by mr. x
I don't reload the segment registers because I don't know how.

Re:GDT in C

Posted: Thu Jan 29, 2004 4:25 pm
by Pype.Clicker
well, if you can afford it, i suggest you run your code in a debug-enabled version of BOCHS. Using the dump_cpu and the trace-on commands accurately, you should be able to better aim your bug ...

btw, the message code you showed tends to convince me the problem comes from the fact you're not reloading segment registers after you're done ... i don't know what exactly you try to do by reloading the GDT, but one thing is certain: if you don't do that
"mov ax,ds; mov ds,ax" thing together with a "jmp CODE_SELECTOR:here; here:", the CPU will keep the old base, options and limit in its internal shadow registers.

Re:GDT in C

Posted: Thu Jan 29, 2004 4:40 pm
by nullify
mr. x wrote: I don't reload the segment registers because I don't know how.
df has source code in the OS FAQ that you can download (queeg.zip):
http://www.mega-tokyo.com/os/os-faq-lin ... ee_kernels

src/bootp/gdt.c, lines 40-45 reload DS, ES, FS, GS, and SS. Lines 56-58 would reload CS via LJMP. (I'm not quite sure why lines 56-58 are commented out, however. They are necessary.)

Re:GDT in C

Posted: Thu Jan 29, 2004 5:37 pm
by mr. x
Whey! It works!
Thanks.

Re:GDT in C

Posted: Fri Jan 30, 2004 1:56 am
by df
yuk i didnt realise that old code was still around! hahah :)

Re:GDT in C

Posted: Fri Jan 30, 2004 2:41 am
by Solar
BTW, what happened to the new (Wiki based) OS FAQ? I can't seem to find it anymore...