Page 14 of 20

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 3:30 pm
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?

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 4:24 pm
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.

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 5:03 pm
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},
}};

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 5:08 pm
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.

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 5:21 pm
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},
}};

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 5:23 pm
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};

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 6:12 pm
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.

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 6:16 pm
by devc1
Are you asking for a 64 bit tss ?

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 6:39 pm
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;
      |                 ^~~~~~~~~

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 9:50 pm
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.

Re: How to make a GDT?

Posted: Sat Oct 29, 2022 10:52 pm
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.

Re: How to make a GDT?

Posted: Sun Oct 30, 2022 3:58 am
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

Re: How to make a GDT?

Posted: Sun Oct 30, 2022 4:03 am
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).

Re: How to make a GDT?

Posted: Sun Oct 30, 2022 8:52 am
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:

Re: How to make a GDT?

Posted: Sun Oct 30, 2022 8:59 am
by devc1
Yeahhh, I am not a fan of reading btw.