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.Octocontrabass wrote:Limine provides a GDT you can use temporarily. You'll need to set up your own GDT at some point, though.
How to make a GDT?
Re: How to make a GDT?
Re: How to make a GDT?
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.
How would I properly setup the 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},
}};
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
The Limine terminal requires the first seven descriptors in your GDT to match the temporary GDT provided by Limine.
Your GDT doesn't even have seven descriptors.
Your GDT doesn't even have seven descriptors.
Re: How to make a GDT?
So then how would I set up the seven descriptors I need? How would I set up 16-bit and 32-bit descriptors?Octocontrabass wrote:The Limine terminal requires the first seven descriptors in your GDT to match the temporary GDT provided by Limine.
Your GDT doesn't even have seven descriptors.
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
You can find more information about segment descriptors in the wiki, the Intel manuals, and the AMD manuals.
Re: How to make a GDT?
Would this be a 16-bit kernel mode code segment? If not, then what would one look like?Octocontrabass wrote:You can find more information about segment descriptors in the wiki, the Intel manuals, and the AMD manuals.
Code: Select all
{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (0 << 7) | 0x00, 0x00},
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
That's a 64-bit kernel mode code segment.zap8600 wrote:Would this be a 16-bit kernel mode code segment?
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 wrote:If not, then what would one look like?
Re: How to make a GDT?
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.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.
Re: How to make a GDT?
https://www.rapidtables.com/convert/num ... o-hex.htmlzap8600 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.
Re: How to make a GDT?
That's really helpful. Thanks.kzinti wrote: https://www.rapidtables.com/convert/num ... o-hex.html
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},
}};
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},
| ^~~~~~~~~~
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
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.zap8600 wrote:Does this look right?
The G, D/B, and L bits all go in the same byte as the upper four bits of the limit.
Re: How to make a GDT?
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 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.
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
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.zap8600 wrote:So how do I fix the limit because the Limine protocol says that the 32-bit limit has to be 0xffffffff.
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.
Yes.zap8600 wrote:And can I "un-shift" the bits?
Re: How to make a GDT?
So does the 0xFFFF limit need to be changed for the 16-bit (and maybe 64-bit) segments?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 how would I do that? would I do something similar to this?Octocontrabass wrote: Yes.
Code: Select all
(1 << 5) | (1 << 7) | 0x0F
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: How to make a GDT?
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 does the 0xFFFF limit need to be changed for the 16-bit (and maybe 64-bit) segments?
Yes. That specific example sets G=1, D/B=0, L=1, and the upper four bits of the limit to 0xF.zap8600 wrote:So how would I do that? would I do something similar to this?