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: Yes. That specific example sets G=1, D/B=0, L=1, and the upper four bits of the limit to 0xF.
I believe this will need to be done for all the segments. So because the lower (four?) bits limit of the 16-bit segments is 0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.

I'm attempting to future-proof here. When I begin to enter user-mode, I know I will need user-mode code and data segments. When I add those to the GDT, do I only have to add 64-bit segments to 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 wrote:So because the lower (four?) bits limit of the 16-bit segments is 0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.
For 16-bit segments, the limit needs to be 0xFFFF bytes, which is either 0xFFFF with G=0 or 0xF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0.

For 32-bit segments, the limit needs to be 0xFFFFFFFF bytes, which can only be 0xFFFFF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0xF.

For 64-bit segments, the limit shouldn't matter. It's a good idea to use the same values as 32-bit segments.
zap8600 wrote:When I add those to the GDT, do I only have to add 64-bit segments to the GDT?
That depends on what type of user mode programs you want to run. If you only want to run 64-bit programs, you only need 64-bit segments.
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:
zap8600 wrote:So because the lower (four?) bits limit of the 16-bit segments is 0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.
For 16-bit segments, the limit needs to be 0xFFFF bytes, which is either 0xFFFF with G=0 or 0xF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0.

For 32-bit segments, the limit needs to be 0xFFFFFFFF bytes, which can only be 0xFFFFF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0xF.

For 64-bit segments, the limit shouldn't matter. It's a good idea to use the same values as 32-bit segments.
I believe that my GDT below is correct.

Code: Select all

FullGDT gdt[32] __attribute__((used)) = {{
	{
		{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
		{0xF, 0x0000, 0x00, 0x9A, (1 << 5) | 0x00, 0x00},
		{0xF, 0x0000, 0x00, 0x92, (1 << 5) | 0x00, 0x00},
		{0xFFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 6) | 0x0F, 0x00},
		{0xFFFFF, 0x0000, 0x00, 0x92, (1 << 5) | (1 << 6) | 0x0F, 0x00},
		{0xFFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 7) | 0X0F, 0x00},
		{0xFFFFF, 0x0000, 0x00, 0x92, (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},
}};
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:I believe that my GDT below is correct.
It is not. It looks like you've switched the G and L bits, and you're still trying to put more than 16 bits in the space for the lower 16 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: It is not. It looks like you've switched the G and L bits, and you're still trying to put more than 16 bits in the space for the lower 16 bits of the limit.
Then is this right?

Code: Select all

FullGDT gdt[32] __attribute__((used)) = {{
	{
		{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
		{0xF, 0x0000, 0x00, 0x9A, (1 << 7) | 0x00, 0x00},
		{0xF, 0x0000, 0x00, 0x92, (1 << 7) | 0x00, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 6) | (1 << 7) | 0x0F, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x92, (1 << 6) | (1 << 7) | 0x0F, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 7) | 0X0F, 0x00},
		{0xFFFF, 0x0000, 0x00, 0x92, (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},
}};
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: How to make a GDT?

Post by devc1 »

Here is what you need :

Code: Select all


struct GDT_ENTRY{ 
                 uint16_t limit_low; 
                 uint16_t base_low; 
                 uint8_t base_mid; 
                 uint8_t access; 
                 uint8_t limit_high : 4; 
                 uint8_t flags : 4; 
                 uint8_t base_high; 
 };
struct GDT{ 
         struct GDT_ENTRY null0; 
         struct GDT_ENTRY kernel_code; 
         struct GDT_ENTRY kernel_data; 
 };
        CpuGdt->kernel_code = (struct GDT_ENTRY){ 0, 0, 0, 0b10011010, 0, 0b1010, 0}; 
         CpuGdt->kernel_data = (struct GDT_ENTRY){ 0, 0, 0, 0b10010010, 0, 0b1000, 0};
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 »

devc1 wrote:Here is what you need :

Code: Select all


struct GDT_ENTRY{ 
                 uint16_t limit_low; 
                 uint16_t base_low; 
                 uint8_t base_mid; 
                 uint8_t access; 
                 uint8_t limit_high : 4; 
                 uint8_t flags : 4; 
                 uint8_t base_high; 
 };
struct GDT{ 
         struct GDT_ENTRY null0; 
         struct GDT_ENTRY kernel_code; 
         struct GDT_ENTRY kernel_data; 
 };
        CpuGdt->kernel_code = (struct GDT_ENTRY){ 0, 0, 0, 0b10011010, 0, 0b1010, 0}; 
         CpuGdt->kernel_data = (struct GDT_ENTRY){ 0, 0, 0, 0b10010010, 0, 0b1000, 0};
This would work with my TSS.
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: How to make a GDT?

Post by devc1 »

Are you asking for a 64 bit tss ?
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 »

devc1 wrote:Are you asking for a 64 bit tss ?
No, I have one. It is that adding limit_high to the gdt_entry_t doesn't work with my TSS and my Null entry. It gives me a warning.

Code: Select all

arch/x86_64/gdt.c:47:17: warning: missing initializer for field 'base_high' of 'gdt_entry_t' [-Wmissing-field-initializers]
   47 |                 {0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
      |                 ^
arch/x86_64/gdt.c:25:17: note: 'base_high' declared here
   25 |         uint8_t base_high;
      |                 ^~~~~~~~~
arch/x86_64/gdt.c:54:17: warning: missing initializer for field 'base_high' of 'gdt_entry_t' [-Wmissing-field-initializers]
   54 |                 {0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00},
      |                 ^
arch/x86_64/gdt.c:25:17: note: 'base_high' declared here
   25 |         uint8_t base_high;
      |                 ^~~~~~~~~
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post by Octocontrabass »

zap8600 wrote:Then is this right?
Those code and data segments look correct to me.
devc1 wrote:Here is what you need :
Your GDT does not meet Limine's requirements. It is not possible to use Limine's terminal with this GDT.
zap8600 wrote:It gives me a warning.
The struct layout is different. You need to rewrite the initializer to match the struct layout.
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: Those code and data segments look correct to me.
Well, something went wrong. Unfortunately, it is pretty late and I can't stay up attempting to debug my OS like I usually do. I'll leave my QEMU log here and I'll get to it when I wake up.
Attachments
qemu.txt
(20.98 KiB) Downloaded 88 times
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: How to make a GDT?

Post by devc1 »

Well, I didn't know about the limine thing.
However, if you want the gdt in assembly here it is :
NASM Syntax and you can relayout it as you want

Code: Select all

    .NULL dq 0 
     .Code: 
         dw 0 
         dw 0 
         db 0 
         db 10011010b 
         db 1010b << 4 ; Limit | Flags << 4 
         db 0 
     .Data: 
         dw 0 
         dw 0 
         db 0 
         db 10010010b 
         db 1000b << 4 ; Limit | Flags << 4 
         db 0
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: How to make a GDT?

Post by devc1 »

I looked in to limines github repo and It seems that limines GDT 32 bit. And you are trying to run 64 bit code in 32 bit mode ? If yes and the kernel loads perfectly into the startup function, I can help you but you will not be able to use the terminal, otherwise you can just create your own terminal.

When you create a kernel, you are nomore dependent of bootloader stuff, the bootloader passed the initdata, now its your turn to startup the OS (a long trip).
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: How to make a GDT?

Post by nexos »

@devc1: read the protocol spec. It's very clear that it enters the CPU into long mode if you want it to. You haven't looked hard enough :wink:
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
devc1
Member
Member
Posts: 439
Joined: Fri Feb 11, 2022 4:55 am
Location: behind the keyboard

Re: How to make a GDT?

Post by devc1 »

Yeahhh, I am not a fan of reading btw.
Post Reply