GDT troubles

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.
Post Reply
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

GDT troubles

Post by Sanchezman »

I've spent some time looking over the wiki's article on setting up the GDT, and I've also spent a fair amount of time looking at other tutorials and explanations, but I still can't initialize it properly (so I can move on to interrupts) and I have a few questions.

The way the wiki is phrased suggests that if I want a paging kernel, all I need to do is set up the GDT to a bare minimum.
Here's the bare minimum I've been led to believe I need: http://wiki.osdev.org/GDT_Tutorial#Flat_Setup
  • Is this correct? Since memory access will be handled by paging, I don't need to worry about specifically setting ring modes for memory blocks, right?

    Could someone explain to me what the reference to the Tss pointer is? I gather that it has some importance for multitasking, but I can't find any information with examples on where to get an initial tss pointer. When I wrote my code, I took the liberty of assuming it null.

    The article gives no information on the struct of a gdt entry. I understand that it says that it's complicated and somewhat outdated, but how am I supposed to form a valid GDT entry without knowing what amount of information I need? Since I can't find this information anywhere on either the tutorial page or the GDT page in the wiki, I made a naive attempt at a GDT entry struct here:

    Code: Select all

    struct gdt_entry
    {
      uint32_t base;
      uint32_t limit;
      char type;
    }typedef gdt_entry gdt_entry_t;
    Based off the aforementioned assumptions, I wrote the following test function to attempt to initialize my GDT:

    Code: Select all

    extern void setGdt(uint32_t, size_t);
    
    //Returns size of initialized GDT
    
    //**TODO**
    //Get working
    //Clean up magic numbers
    size_t gdt_init(gdt_entry_t* gdt){
    
      gdt[0].base = 0;
      gdt[0].limit = 0;
      gdt[0].type = 0;
      gdt[1].base = 0;
      gdt[1].limit = 0xffffffff;
      gdt[1].type = 0x9A;
      gdt[2].base = 0;
      gdt[2].limit = 0xffffffff;
      gdt[2].type = 0x92;
      gdt[3].base = 0;    //TSS is null
      gdt[3].limit = sizeof(void*);   //Assume Tss is a pointer
      gdt[3].type = 0x89;
    
      //GDT is of size 4.
      setGdt(gdt, 4);
      return 4;
    }
    Also, for completeness' sake, here is my definition of setGdt in assembly:

    Code: Select all

    	[GLOBAL setGdt]    ; Allows the C code to call setGdt().
    
    	gdtr DW 0 ; For limit storage
    	DD 0 ; For base storage
     
    setGdt:
    	MOV   EAX, [esp + 4]
    	ADD	EAX,0x100000  ;;Start of kernel
    	MOV   [gdtr + 2], EAX
    	MOV   AX, [ESP + 8]
    	MOV   [gdtr], AX
    	LGDT  [gdtr]
    
    	;; Now flush
    	JMP   0x08:reload_CS
    reload_CS:
    	MOV   AX, 0x10
    	MOV   DS, AX
    	MOV   ES, AX
    	MOV   FS, AX
    	MOV   GS, AX
    	MOV   SS, AX
    	RET
Now, it's obvious that I'm wrong somewhere since my kernel crashes whenever I try my GDT initialization.

Thanks in advance for any and all help.
FallenAvatar
Member
Member
Posts: 283
Joined: Mon Jan 03, 2011 6:58 pm

Re: GDT troubles

Post by FallenAvatar »

Might want to take a look at the GDT Article on the wiki here. Also, this section may be of help to you: http://wiki.osdev.org/GDT_Tutorial#Some ... _life_easy

- Monk
User avatar
iansjack
Member
Member
Posts: 4707
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: GDT troubles

Post by iansjack »

Also, it's all explained in the Intel Programmers Manuals. These are essential reading if you want to do OS development.
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

Re: GDT troubles

Post by Sanchezman »

Thanks for the helpful advice, both of you. I'll definitely check out the intel programmer's manuals then.
CelestialMechanic
Member
Member
Posts: 52
Joined: Mon Oct 11, 2010 11:37 pm
Location: Milwaukee, Wisconsin

Re: GDT troubles

Post by CelestialMechanic »

What is wrong with the following code excerpt?

Code: Select all

MOV   AX, 0x10
MOV   DS, AX
MOV   ES, AX
MOV   FS, AX
MOV   GS, AX
MOV   SS, AX
RET
What is the value of the (E)SP register? Always, always, always set the stack pointer after loading a new value into SS. The microprocessor will process the instruction after the MOV SS without interruption so that no interrupt will occur with the stack in an undefined state.

You didn't change SP? Was your stack segment previously 16 bits and is now 32 bits? Are you sure the upper 16 bits of ESP are clear? Make certain. Load ESP with a 32 bit value after the MOV SS,AX. You'll be glad you did.
Microsoft is over if you want it.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: GDT troubles

Post by Gigasoft »

I suggest that this silly "tutorial" should be removed or tidied up. For this website to be taken seriously, we can't have the main page linking to material written by some inexperienced amateur during the very early days of hobby PC OS development. I believe there is a direct cause and effect relationship between these unhelpful, confusing tutorials and the general theme of many of the topics posted here.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: GDT troubles

Post by Gigasoft »

CelestialMechanic wrote:What is wrong with the following code excerpt?
There is actually nothing wrong with that code. The stack is fine, and was 32 bit to begin with. The purpose of this code is not to relocate the stack, but to reload the segment registers with known values. Usually, I would consider loading a flat data selector into FS and GS a bizarre antipattern, but in this case the original values of FS and GS are unknown, so at this point it is excusable. I would prefer to load them with 0 if you are not using them, though, especially if they are going to get saved and restored a lot. Loading a null selector is slightly faster than loading a non-null selector.

Interestingly, the Multiboot specification states that FS and GS must be set to flat data selectors. Was the author of that specification under the influence of one of these tutorials?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: GDT troubles

Post by Combuster »

I would consider loading a flat data selector into FS and GS a bizarre antipattern
Interestingly, the Multiboot specification states that FS and GS must be set to flat data selectors. Was the author of that specification under the influence of one of these tutorials?
Think about it the other way:
- Leave it undefined: Security issue, bad idea.
- Load a predefined base into them: way too specific to be meaningful.
- Make it a null selector: Any compiler-generated code using FS or GS will crash.
- Make it a flat selector: None of the above problems. The generated binary is even shorter than the previous item :wink:

The point is mostly that you don't forget FS and GS. What values you want them to have is actually pretty arbitrary and the moment you start adding either TLS or SwapGS you end up overriding either "sane default" with something specific to your OS.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply