GDT in C

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
mr. x

GDT in C

Post 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;
}

mr. x

Re:GDT in C

Post by mr. x »

Oh, BTW:
I get a General Protection Fault with that code. ;)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:GDT in C

Post 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.
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:GDT in C

Post by df »

why are you enabling paging straight after loading GDT? is your paging setup properly in CR3?
-- Stu --
mr. x

Re:GDT in C

Post by mr. x »

I tested to set the G bit (granularity) and it didn't help...
high 32 in GDT[1] is 110011111001101000000000
mr. x

Re:GDT in C

Post 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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:GDT in C

Post 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 ?
mr. x

Re:GDT in C

Post 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
nullify

Re:GDT in C

Post 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;
mr. x

Re:GDT in C

Post by mr. x »

I don't reload the segment registers because I don't know how.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:GDT in C

Post 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.
nullify

Re:GDT in C

Post 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.)
mr. x

Re:GDT in C

Post by mr. x »

Whey! It works!
Thanks.
User avatar
df
Member
Member
Posts: 1076
Joined: Fri Oct 22, 2004 11:00 pm
Contact:

Re:GDT in C

Post by df »

yuk i didnt realise that old code was still around! hahah :)
-- Stu --
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:GDT in C

Post by Solar »

BTW, what happened to the new (Wiki based) OS FAQ? I can't seem to find it anymore...
Every good solution is obvious once you've found it.
Post Reply