question about 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.
Post Reply
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

question about gdt

Post by clavin123 »

i am following Jamesm tut
and i had some prob with the gdt.

1. in the tut it says "The segment's window should start at 0x00000000 and extend to 0xFFFFFFFF (the end of memory)"
but it also says segments are windows into main memory. now if the window extends whole area how can there be segments. for example i was assuming that if i had 32megs of memory i wud divide it into chunks of 2meg where each 2mb wud begin with base 0 and end at 2mb(in hex)

2. correct me if i am wrong but i was assuming that in james tut we are dealing with a main memory of 32 mb but in the follwing code

Code: Select all

struct gdt_entry_struct
 {
    u16int limit_low;           // The lower 16 bits of the limit.
    u16int base_low;            // The lower 16 bits of the base.
    u8int  base_middle;         // The next 8 bits of the base.
    u8int  access;              // Access flags, determine what ring this segment can be used in.
    u8int  granularity;
    u8int  base_high;           // The last 8 bits of the base.
 } __attribute__((packed));
 typedef struct gdt_entry_struct gdt_entry_t; 
we have taken only 24 bits for limit and base which can then reference only 16mb. so am i wrong

more importantly there are two declaration for both base and limit.
coudnt we have taken a single u32int for both base and limit??

and finally in the following code

Code: Select all

void init_descriptor_tables()
 {
    // Initialise the global descriptor table.
    init_gdt();
 }
 
static void init_gdt()
 {
    gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
    gdt_ptr.base  = (u32int)&gdt_entries;
 
   gdt_set_gate(0, 0, 0, 0, 0);                // Null segment
    gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
    gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
    gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
    gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment
 
   gdt_flush((u32int)&gdt_ptr);
 }
 
// Set the value of one GDT entry.
 static void gdt_set_gate(s32int num, u32int base, u32int limit, u8int access, u8int gran)
 {
    gdt_entries[num].base_low    = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFF;
    gdt_entries[num].base_high   = (base >> 24) & 0xFF;
 
   gdt_entries[num].limit_low   = (limit & 0xFFFF);
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;
 
   gdt_entries[num].granularity |= gran & 0xF0;
    gdt_entries[num].access      = access;
 } 
since the base is 0 why all the & and left shifting the base in the gdt_set_gate function
can anyone explain the gdt_set_gate a lil bit?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: question about gdt

Post by Solar »

Base 0x0 and limit 0xffffffff are chosen to achieve what is called the "flat memory" model, where segments are not used for memory separation at all. Check out Segmentation, section "Notes regarding C".

Your other questions are answered by the Intel Manuals. There is no way around actually reading them, especially volume #3. Explaining the GDT "real quick" would do more harm than good, since I get the impression that you are missing several basic details about segments and descriptors...

Last but not least, some effort in actually writing correct English would be appreciated. "Tutorial" instead of "tut", "would" instead of "wud", plus some capitalization can do wonders for readability.
Every good solution is obvious once you've found it.
Rudster816
Member
Member
Posts: 141
Joined: Thu Jun 17, 2010 2:36 am

Re: question about gdt

Post by Rudster816 »

clavin123 wrote: 1. in the tut it says "The segment's window should start at 0x00000000 and extend to 0xFFFFFFFF (the end of memory)"
but it also says segments are windows into main memory. now if the window extends whole area how can there be segments. for example i was assuming that if i had 32megs of memory i wud divide it into chunks of 2meg where each 2mb wud begin with base 0 and end at 2mb(in hex)
Segmentation is an old, and relatively useless memory protection feature. While in theory you could use it for memory protection on x86 platforms, paging is about 1000 times better. So for the purpose of simplicity, most OS developers will setup a 'flat' memory model and pretend that segmentation doesn't exist to the extent that is possible.

Also, what segments provide a "window" into depends on rather or not you have paging enabled. Without paging, the CPU will translate a linear address (the one's you to provide to it with software) into a physical address through way of the GDT. With paging enabled, the CPU will translate the linear address into a virtual address using the same method, however, it will then translate that virtual address into a physical one through way of the paging structures pointed to by CR3.
clavin123 wrote: 2. correct me if i am wrong but i was assuming that in james tut we are dealing with a main memory of 32 mb but in the follwing code

Code: Select all

struct gdt_entry_struct
 {
    u16int limit_low;           // The lower 16 bits of the limit.
    u16int base_low;            // The lower 16 bits of the base.
    u8int  base_middle;         // The next 8 bits of the base.
    u8int  access;              // Access flags, determine what ring this segment can be used in.
    u8int  granularity;
    u8int  base_high;           // The last 8 bits of the base.
 } __attribute__((packed));
 typedef struct gdt_entry_struct gdt_entry_t; 
we have taken only 24 bits for limit and base which can then reference only 16mb. so am i wrong

more importantly there are two declaration for both base and limit.
coudnt we have taken a single u32int for both base and limit??
That structure is designed that way because that's the way the CPU will see it. If you want an explanation of what every entry means, read GDT's here.
clavin123 wrote: since the base is 0 why all the & and left shifting the base in the gdt_set_gate function
can anyone explain the gdt_set_gate a lil bit?
The base is only 0 if thats what given to the function. I believe it's obvious as to why the gdt_set_gate function doesn't assume a parameter it's given is 0.



A bit of advice too. Read all of the relevant Wiki entries and Intel manual chapters before you post question. Almost everything you could possibly need to know is answered in those two locations. If at first you don't understand something, reread it again (this is especially true of technical manuals) and you'll start to understand it more. You really can't survive without being able to understand technical documentation\articles. OS development isn't the kind of thing that suites hand holding tutorials well.

Intel Manual:
http://download.intel.com/products/proc ... 325462.pdf
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

@solar ok i wil try to adhere to your advice.
and pardon me for such noobish questions.
That structure is designed that way because that's the way the CPU will see it. If you want an explanation of what every entry means, read GDT's here.
]
I thought i was missing something. Since i havent worked much with bits and shifting so i asked. anyways thanks for pointing that out.
The base is only 0 if thats what given to the function. I believe it's obvious as to why the gdt_set_gate function doesn't assume a parameter it's given is 0.
but can i assume that since we are working in a flat memory model the only time this function will be called is during initiatialization and we it will always get the base paramater as 0 from us?


apart from that i have just a few more qs about the gdt

in the following code of gdt pointer structure

Code: Select all

struct gdt_ptr_struct
 {
    u16int limit;               // The upper 16 bits of all selector limits.
    u32int base;                // The address of the first gdt_entry_t struct.
 }
  __attribute__((packed));
 typedef struct gdt_ptr_struct gdt_ptr_t; 
limit was defined the upper 16 bits of all selector limits.now what does the 16 bits have to do with this?? Because I was assuming that limit was just an offset from the base giving us the size of the table.

Another qs is that i read the gdt wiki and there it said "The size is the size of the table subtracted by 1. This is because the maximum value of size is 65535, while the GDT can be up to 65536 bytes (a maximum of 8192 entries). Further no GDT can have a size of 0."
but even after that reason i dont understand as to why we need to subtract 1. i mean all i need to is ensure that my limit(offset) is <=65535 .

Lastly a not so important question
Is it possible for paging and segmentation to be enabled at same time
like for some segments granularity is 0 while for others it is 1?
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: question about gdt

Post by bluemoon »

clavin123 wrote:
The base is only 0 if thats what given to the function. I believe it's obvious as to why the gdt_set_gate function doesn't assume a parameter it's given is 0.
but can i assume that since we are working in a flat memory model the only time this function will be called is during initiatialization and we it will always get the base paramater as 0 from us?
It's for readability. If you care about such (premature) optimization, don't worry, constant parameters are resolved by most modern optimizer and thus the code generated should be effective zeros there.
clavin123 wrote: Another qs is that i read the gdt wiki and there it said "The size is the size of the table subtracted by 1. This is because the maximum value of size is 65535, while the GDT can be up to 65536 bytes (a maximum of 8192 entries). Further no GDT can have a size of 0."
but even after that reason i dont understand as to why we need to subtract 1.
The 1 is defined by the CPU designer. I believe they have good reason but it doesn't matter much, I would just follow.
clavin123 wrote: Is it possible for paging and segmentation to be enabled at same time
like for some segments granularity is 0 while for others it is 1?
You cannot disable segments, and when you enable paging, both are activated.
When we talk about flat model we just do not switch segments(except some special situation) to minimize penalty involved.
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

thnx i guess that resolved much of my doubt
Rudster816
Member
Member
Posts: 141
Joined: Thu Jun 17, 2010 2:36 am

Re: question about gdt

Post by Rudster816 »

The limit in the "GDT Pointer" has nothing to do with address translation (it has nothing to do with the 'limit' part of GDT entries). The limit in the GDT pointer tells the CPU how many valid entries there are in the GDT. That way if you try to load, say, 0x20 into a segment register even though you only had 3 entries in your GDT, the CPU wont treat the garbage after your GDT as a valid GDT entry. The reason it has to be (size of GDT - 1) and not just (size of GDT) is because you are allowed to have a GDT that is 65536 bytes long (the limit represents the size of the GDT in bytes, NOT the number of entries), which you can't express directly in a two byte integer.
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

thnx rudster for that fine explaination.
l

apart from that
in the following code

Code: Select all

...
 extern void idt_flush(u32int);
 ...
 static void init_idt();
 static void idt_set_gate(u8int,u32int,u16int,u8int);
 ...
 idt_entry_t idt_entries[256];
 idt_ptr_t   idt_ptr;
 ...
 void init_descriptor_tables()
 {
   init_gdt();
   init_idt();
 }
 ...
 static void init_idt()
 {
    idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
    idt_ptr.base  = (u32int)&idt_entries;
 
   memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
 
   idt_set_gate( 0, (u32int)isr0 , 0x08, 0x8E);
    idt_set_gate( 1, (u32int)isr1 , 0x08, 0x8E);
    ...
    idt_set_gate(31, (u32int)isr32, 0x08, 0x8E);
 
   idt_flush((u32int)&idt_ptr);
 }
 
static void idt_set_gate(u8int num, u32int base, u16int sel, u8int flags)
 {
    idt_entries[num].base_lo = base & 0xFFFF;
    idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
 
   idt_entries[num].sel     = sel;
    idt_entries[num].always0 = 0;
    // We must uncomment the OR below when we get to using user-mode.
    // It sets the interrupt gate's privilege level to 3.
    idt_entries[num].flags   = flags /* | 0x60 */;
 } 
we used memset to initialize the whole idt table with 0
why did we do this here? we didnt do it in case of gdt


also in the tutorial http://www.jamesmolloy.co.uk/tutorial_h ... nesis.html
before calling main(in boot.s) we had used the cli instruction and hadnt used a sti instruction to unblock interrupts
so how come interuppts are still working?
Last edited by clavin123 on Thu Mar 22, 2012 10:07 am, edited 2 times in total.
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

#dnt bother with this particular reply. i got it sorted(or should i say it was a wrong qs)
also i would like to ask why is it showing unhandled interrupt instead of interrupt recieved?
in the isr.c there is folllowing code

Code: Select all

#include "common.h"
#include "isr.h"
#include "monitor.h"

// This gets called from our ASM interrupt handler stub.
void isr_handler(registers_t regs)
{
   monitor_write("recieved interrupt: ");
   monitor_write_dec(regs.int_no);
   monitor_put('\n');
} 
Last edited by clavin123 on Thu Mar 22, 2012 10:05 am, edited 1 time in total.
invalid
Member
Member
Posts: 60
Joined: Thu Feb 23, 2012 8:39 am

Re: question about gdt

Post by invalid »

clavin123 wrote:we used memset to initialize the whole idt table with 0
why did we do this here?
IMHO that's a good idea to initialize all variables, structures, buffers etc. Just last night I chased a bug, which was: internal kernel structure was not properly initialized and after reboot it contained invalid (pre-reboot) data :twisted:
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

ydoom wrote:
clavin123 wrote:we used memset to initialize the whole idt table with 0
why did we do this here?
IMHO that's a good idea to initialize all variables, structures, buffers etc. Just last night I chased a bug, which was: internal kernel structure was not properly initialized and after reboot it contained invalid (pre-reboot) data :twisted:
ok so i guess its a safety measure
well thats good. well i have one last doubt regarding idt
we used the following to set idt entries

Code: Select all

idt_set_gate( 0, (u32int)isr0 , 0x08, 0x8E);
where 8E is flag
in the tutorial it says that i need to set the flag to 10000110
but that translates to 86 in hex not 8E(but the code runs with 8E)
So whats the mistake here?
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: question about gdt

Post by bluemoon »

That bit is the D-bit, according to the manual: D: Size of gate: 1 = 32 bits; 0 = 16 bits

EDIT: I actually check the tutorial and see this:

Code: Select all

static void init_idt()
{
   idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
   idt_ptr.base  = (u32int)&idt_entries;

   memset(&idt_entries, 0, sizeof(idt_entry_t)*256);

   idt_set_gate( 0, (u32int)isr0 , 0x08, 0x8E);
   idt_set_gate( 1, (u32int)isr1 , 0x08, 0x8E);
   ...
   idt_set_gate(31, (u32int)isr32, 0x08, 0x8E);

   idt_flush((u32int)&idt_ptr);
}
Where do you see 0x86?
clavin123
Posts: 23
Joined: Mon Mar 19, 2012 2:01 am

Re: question about gdt

Post by clavin123 »

exactly my point
it should be 0x86 according to me
because if you look at the flag diagram of the tutorial
you see that lower 5 bits must always be 00110
next 2 higher bits descirbe privilege level so they are 00
and the most significant bit describes present bit so it is 1
it makes up to 100001100 which is 0x86 and not 0x8E
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: question about gdt

Post by bluemoon »

clavin123 wrote:you see that lower 5 bits must always be 00110
Are you looking at something else?

According to my manual,
That byte is:
[P:1] [DPL:2][0][D:1][110], or P DPL 0 D 1 1 0

EDIT: Oh I misunderstood what you said. Yes, I realize that the image in the tutorial says that is always 00110, which is not accurate.
Post Reply