How to make a GDT?

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.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

Octocontrabass wrote:Limine provides a GDT you can use temporarily. You'll need to set up your own GDT at some point, though.
The subject of making the GDT is very confusing to me. Thankfully, I've been looking at some existing code, so I have a (somewhat) good idea about what I need to do. I'll be back, but I'm going to give it a good try before I do.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

I don't think I setup my GDT correctly. When booting, the system halts because Limine wasn't able to start the terminal. In the Limine protocol documentation, it says that specific segments are required, but I'm not sure how to set them up. Here is my GDT.

Code: Select all

FullGDT gdt[32] __attribute__((used)) = {{ 
         { 
                 {0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00}, 
                 {0xFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 7) | 0x0F, 0x00}, 
                 {0xFFFF, 0x0000, 0x00, 0x92, (1 << 5) | (1 << 7) | 0x0F, 0x00}, 
                 {0xFFFF, 0x0000, 0x00, 0xFA, (1 << 5) | (1 << 7) | 0x0F, 0x00}, 
                 {0xFFFF, 0x0000, 0x00, 0xF2, (1 << 5) | (1 << 7) | 0x0F, 0x00}, 
                 {0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00}, 
         }, 
         {0x00000000, 0x00000000}, 
         {0x0000, 0x0000000000000000}, 
         {0,{0,0,0},0,{0,0,0,0,0,0,0},0,0,0}, 
 }};
How would I properly setup the GDT?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

So then how would I set up the seven descriptors I need? How would I set up 16-bit and 32-bit descriptors?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

You can find more information about segment descriptors in the wiki, the Intel manuals, and the AMD manuals.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

Octocontrabass wrote:You can find more information about segment descriptors in the wiki, the Intel manuals, and the AMD manuals.
Would this be a 16-bit kernel mode code segment? If not, then what would one look like?

Code: Select all

{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (0 << 7) | 0x00, 0x00},
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:Would this be a 16-bit kernel mode code segment?
That's a 64-bit kernel mode code segment.
zap8600 wrote:If not, then what would one look like?
The L and D/B bits determine whether a segment is 16-bit, 32-bit, or 64-bit. Both of those bits need to be clear for a 16-bit code segment.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

Octocontrabass wrote: The L and D/B bits determine whether a segment is 16-bit, 32-bit, or 64-bit. Both of those bits need to be clear for a 16-bit code segment.
My bad. Bits are a bit confusing for me, so I'm not exactly sure how to do this. Some help on bits would be great.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: How to make a GDT?

Post by kzinti »

zap8600 wrote:My bad. Bits are a bit confusing for me, so I'm not exactly sure how to do this. Some help on bits would be great.
https://www.rapidtables.com/convert/num ... o-hex.html
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

That's really helpful. Thanks.
I think I might have all the segments done. Does this look right?

Code: Select all

FullGDT gdt[32] __attribute__((used)) = {{
	{
		{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x9A, 0x08, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x92, 0x08, 0x00},
		{0xFFFFFFFF, 0x0000, 0x00, 0x9A, 0x08, 0x00},
		{0xFFFFFFFF, 0x0000, 0x00, 0x92, 0x08, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x9A, 0x0A, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x92, 0x0A, 0x00},
		{0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00},
	},
	{0x00000000, 0x00000000},
	{0x0000, 0x0000000000000000},
	{0,{0,0,0},0,{0,0,0,0,0,0,0},0,0,0},
}};
If it is, then I got this warning.

Code: Select all

arch/x86_64/gdt.c:49:18: warning: conversion from 'unsigned int' to 'short unsigned int' changes value from '4294967295' to '65535' [-Woverflow]
   49 |                 {0xFFFFFFFF, 0x0000, 0x00, 0x9A, 0x08, 0x00},
      |                  ^~~~~~~~~~
arch/x86_64/gdt.c:50:18: warning: conversion from 'unsigned int' to 'short unsigned int' changes value from '4294967295' to '65535' [-Woverflow]
   50 |                 {0xFFFFFFFF, 0x0000, 0x00, 0x92, 0x08, 0x00},
      |                  ^~~~~~~~~~
If it isn't, then I don't know what I'm doing wrong.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:Does this look right?
No. You're trying to put 32 bits in a space that can only hold 16 bits, and it looks like the G, D/B, and L bits are shifted by 4 bits.

The G, D/B, and L bits all go in the same byte as the upper four bits of the limit.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

Octocontrabass wrote: No. You're trying to put 32 bits in a space that can only hold 16 bits, and it looks like the G, D/B, and L bits are shifted by 4 bits.

The G, D/B, and L bits all go in the same byte as the upper four bits of the limit.
So how do I fix the limit because the Limine protocol says that the 32-bit limit has to be 0xffffffff. And can I "un-shift" the bits?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:So how do I fix the limit because the Limine protocol says that the 32-bit limit has to be 0xffffffff.
The limit is split into two parts in the GDT. Refer to the data structure to see where all the bits for the limit go.

You'll notice that there are only 20 bits for the limit, which means 0xFFFFFFFF doesn't fit. However, 0xFFFFFFFF bytes is equal to 0xFFFFF pages, and when G=1 the limit is measured in pages instead of bytes. So, you can set the limit to 0xFFFFF and G=1 in your descriptor to meet Limine's requirement for a limit of 0xFFFFFFFF bytes.
zap8600 wrote:And can I "un-shift" the bits?
Yes.
zap8600
Member
Member
Posts: 195
Joined: Tue Nov 02, 2021 11:26 am
Libera.chat IRC: zap8600

Re: How to make a GDT?

Post by zap8600 »

Octocontrabass wrote: The limit is split into two parts in the GDT. Refer to the data structure to see where all the bits for the limit go.

You'll notice that there are only 20 bits for the limit, which means 0xFFFFFFFF doesn't fit. However, 0xFFFFFFFF bytes is equal to 0xFFFFF pages, and when G=1 the limit is measured in pages instead of bytes. So, you can set the limit to 0xFFFFF and G=1 in your descriptor to meet Limine's requirement for a limit of 0xFFFFFFFF bytes.
So does the 0xFFFF limit need to be changed for the 16-bit (and maybe 64-bit) segments?
Octocontrabass wrote: Yes.
So how would I do that? would I do something similar to this?

Code: Select all

(1 << 5) | (1 << 7) | 0x0F
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:So does the 0xFFFF limit need to be changed for the 16-bit (and maybe 64-bit) segments?
The 16-bit segments are supposed to have a limit of 0xFFFF bytes, so you need to either set the limit to 0xFFFF with G=0 or set the limit to 0xF with G=1. The limit is ignored for 64-bit segments, but it's a good idea to set it to 0xFFFFF with G=1 to ensure compatibility.
zap8600 wrote:So how would I do that? would I do something similar to this?
Yes. That specific example sets G=1, D/B=0, L=1, and the upper four bits of the limit to 0xF.
Post Reply