Page 2 of 20

Re: How to make a GDT?

Posted: Tue Aug 16, 2022 3:08 pm
by Schol-R-LEA
Ah, OK, thank you for that correction.

Re: How to make a GDT?

Posted: Tue Aug 16, 2022 3:48 pm
by zap8600
Schol-R-LEA wrote: Now, if you want to use a C struct to organize that memory, you will want something like this:

Code: Select all

struct __attribute__((packed, aligned(4))) GDT 
{
    uint16_t base_low;
    uint16_t limit_low;
    uint8_t base_mid;
    uint8_t access;
    uint8_t limit_high_and_flags;
    uint8_t base_high;
};
So if I'm correct, I'll have 4 of these structs set up.
So how do I load this into the GDT?

Re: How to make a GDT?

Posted: Tue Aug 16, 2022 4:00 pm
by Octocontrabass
zap8600 wrote:So if I'm correct, I'll have 4 of these structs set up.
Specifically an array of four of these structs.
zap8600 wrote:So how do I load this into the GDT?
The array of structs is your GDT. Are you asking how to put information into your GDT, or are you asking how to tell the CPU to use your GDT?

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 10:50 am
by zap8600
Octocontrabass wrote: The array of structs is your GDT. Are you asking how to put information into your GDT, or are you asking how to tell the CPU to use your GDT?
Sorry. I was confused.
I meant telling the CPU where the table is. Like this. My inline assembly is bad, and I'm very dumb, so I'm not exactly sure how to do it.
Also, how would I find the values for base_low, mid and high? Same question for limit_low and limit_high_and_flags.
Also, how would I add both limit_high and the flags to limit_high_and_flags?
Sorry if this is too many questions. I'm just dumb and confused.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 11:23 am
by iansjack
You don’t “find” those values, you choose them according to your requirements. Where do you want your segments to start; how big do you want them to be; those are design decisions that you make.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 11:51 am
by Octocontrabass
zap8600 wrote:I meant telling the CPU where the table is.
Create a GDTR descriptor (you can also use a struct) and then use the LGDT instruction to load the GDTR descriptor into GDTR. After you tell the CPU where your GDT is, you should load new selectors into the segment registers. Your code might look something like this, if you use a struct for the GDTR descriptor:

Code: Select all

struct __attribute__((packed)) GDTR
{
    uint16_t limit;
    uint32_t base;
};

void example( uint32_t base, uint16_t limit )
{
    struct GDTR gdtr = { limit, base };
    asm( "lgdt %0" :: "m"(gdtr) );
    asm( "ljmp %0,$1f\n1:" :: "i"(KERNEL_CODE_SEG) );
    asm( "mov %0, %%ds" :: "r"(KERNEL_DATA_SEG) );
    asm( "mov %0, %%es" :: "r"(KERNEL_DATA_SEG) );
    asm( "mov %0, %%ss" :: "r"(KERNEL_DATA_SEG) );
    //asm( "mov %0, %%fs" :: "r"(KERNEL_FS_SEG) );
    //asm( "mov %0, %%gs" :: "r"(KERNEL_GS_SEG) );
}
Unlike the earlier example, this struct must be packed because the compiler would insert padding otherwise. Alignment is unnecessary.
zap8600 wrote:Also, how would I find the values for base_low, mid and high?
Take your base address and put the low 16 bits into base_low, the next 8 bits into base_mid, and the top 8 bits into base_high.
zap8600 wrote:Same question for limit_low and limit_high_and_flags.
Take your limit and put the low 16 bits into limit_low and the high four bits into limit_high_and_flags. The limit is only 20 bits; it indicates either bytes or pages according to the granularity flag.
zap8600 wrote:Also, how would I add both limit_high and the flags to limit_high_and_flags?
The high four bits of the limit go into the low four bits of limit_high_and_flags. Four bits of flags go into the high four bits of limit_high_and_flags. You can use bitwise operations to place the values you want in the correct locations. The Intel and AMD manuals have excellent diagrams showing where everything goes.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 3:31 pm
by zap8600
Octocontrabass wrote:Create a GDTR descriptor (you can also use a struct) and then use the LGDT instruction to load the GDTR descriptor into GDTR. After you tell the CPU where your GDT is, you should load new selectors into the segment registers. Your code might look something like this, if you use a struct for the GDTR descriptor:

Code: Select all

struct __attribute__((packed)) GDTR
{
    uint16_t limit;
    uint32_t base;
};

void example( uint32_t base, uint16_t limit )
{
    struct GDTR gdtr = { limit, base };
    asm( "lgdt %0" :: "m"(gdtr) );
    asm( "ljmp %0,$1f\n1:" :: "i"(KERNEL_CODE_SEG) );
    asm( "mov %0, %%ds" :: "r"(KERNEL_DATA_SEG) );
    asm( "mov %0, %%es" :: "r"(KERNEL_DATA_SEG) );
    asm( "mov %0, %%ss" :: "r"(KERNEL_DATA_SEG) );
    //asm( "mov %0, %%fs" :: "r"(KERNEL_FS_SEG) );
    //asm( "mov %0, %%gs" :: "r"(KERNEL_GS_SEG) );
}
Unlike the earlier example, this struct must be packed because the compiler would insert padding otherwise. Alignment is unnecessary.
I see what I'm doing wrong. I'm confusing the GDT struct for the Segment Struct. I'm very dumb.
iansjack wrote:You don’t “find” those values, you choose them according to your requirements. Where do you want your segments to start; how big do you want them to be; those are design decisions that you make.
So what should the size of it be? Do I find the size in the Intel and AMD Manual? I'm not really sure how large it should be. I'm using the segments from here.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 3:50 pm
by Octocontrabass
zap8600 wrote:So what should the size of it be? Do I find the size in the Intel and AMD Manual? I'm not really sure how large it should be. I'm using the segments from here.
You don't "find" the size, you choose it. How do you want to use segments in your OS? Do you want to use segments at all? The values that go into your GDT depend on what you want the segments to do in your OS.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 4:05 pm
by zap8600
Octocontrabass wrote: You don't "find" the size, you choose it. How do you want to use segments in your OS? Do you want to use segments at all? The values that go into your GDT depend on what you want the segments to do in your OS.
Well I would like to setup Userspace at some point. I also thought that the IDT required the GDT.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 4:51 pm
by Octocontrabass
zap8600 wrote:Well I would like to setup Userspace at some point. I also thought that the IDT required the GDT.
Both of those do require a GDT, but your GDT doesn't have to set up segmentation - you can use a "flat" setup that bypasses segmentation as much as possible.

So, do you want your OS to use segmentation? Or would you prefer the "flat" memory model that doesn't use segmentation?

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 5:32 pm
by zap8600
Octocontrabass wrote: Both of those do require a GDT, but your GDT doesn't have to set up segmentation - you can use a "flat" setup that bypasses segmentation as much as possible.

So, do you want your OS to use segmentation? Or would you prefer the "flat" memory model that doesn't use segmentation?
If it isn't necessary, then I won't add it.
So then what would the base and limit of the GDT be? Would it just be 0 for both?

Also, does paging require segmentation?

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 5:44 pm
by Octocontrabass
zap8600 wrote:So then what would the base and limit of the GDT be? Would it just be 0 for both?
For a flat memory model, the base of the code and data segments should be 0 and the limit should be 0xFFFFFFFF bytes (0xFFFFF pages).

The base of the GDT itself is the address of the GDT. The limit is one less than the size of the GDT in bytes.
zap8600 wrote:Also, does paging require segmentation?
No. You can bypass segmentation and still use paging.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 7:10 pm
by zap8600
I'm unsure how to write the setGDT function from here with inline assembly. How would I write it with the GDT descriptor struct

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 7:15 pm
by Octocontrabass
zap8600 wrote:I'm unsure how to write the setGDT function from here with inline assembly. How would I write it with the GDT descriptor struct
I already gave you example code for that.

Re: How to make a GDT?

Posted: Wed Aug 17, 2022 7:34 pm
by zap8600
I'm sorry. I just wasn't sure it it would wotk with GRUB.
Anyways, the OS booted with the GDT code. Now I have to figure out how to add newline support and a terminal scrolling implementation into the terminal driver. I'm an idiot, so it'll take a while for me to figure out. Then I need to add interrupts, the PIT, and the keyboard. I'll probably return here