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.
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: How to make a GDT?

Post by Schol-R-LEA »

Ah, OK, thank you for that correction.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
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 »

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?
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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?
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 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.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to make a GDT?

Post 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.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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.
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: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.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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.
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 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.
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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?
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: 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?
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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.
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'm unsure how to write the setGDT function from here with inline assembly. How would I write it with the GDT descriptor struct
Octocontrabass
Member
Member
Posts: 5562
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to make a GDT?

Post 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.
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'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
Post Reply