Page 1 of 1

Expand down stack segment setting on x86

Posted: Wed Sep 28, 2011 7:31 am
by RajivKumarSrivastav
Hi All,

I got stuck in setting the base & limit for stack protection :( .
Can some one explain the idea of Expand down stack segment please? I dont get enough information from Intel's System Programming Guide 1.
I want to use expand down stack from address 0xffff,0000 to 0xfffe,0000 ( 64KB) in kernel mode. G (Granularity flag) bit is set to 1 for 4KB increments.
D/B is 1, making operation size as 32 bit pointer.
What should be the value of Segment Descriptor for Stack segment with above required information? Is it related with Real & Protected mode?

Code: Select all

void Init_MicroKernel(){                // entry function for kernel 
gdt_install();  // 1st line in this function
 
}
void setkgdt(uint32 index, uint16 low, uint8 mid, uint8 high, uint16 limit, uint8 access, uint8 gran) {
   kgdt[index].seglimit = limit;
   kgdt[index].lowbase = low;
   kgdt[index].midbase = mid;
   kgdt[index].access = access;
   kgdt[index].granularity = gran;
   kgdt[index].highbase = high;
}

void gdt_install() {
   desc gdtp;   
   setkgdt(0, 0, 0, 0, 0, 0, 0);
   setkgdt(1, 0, 0, 0, 0xFFFF, 0x9B, 0xCF);  // code at 0x8
   setkgdt(2, 0, 0, 0, 0xFFFF, 0x93, 0xCF);   // data
   setkgdt(3, 0x0, 0xFF, 0xFF, 0xFFFD, 0x97, 0xCF); // stack
   setkgdt(4, 0, 0, 0, 0, 0, 0); 
  
   gdtp.limit = (sizeof (gdt_entry) * MAX_GDT_ENTRIES) - 1;
   gdtp.base = (uint32)kgdt;
   InstallGdt((uint32)&gdtp);
}
InstallGdt:
        mov 4(%esp), %eax
        lgdt (%eax)
        mov $DATA_SEL, %ax  /* DATA_SEL  equals =0x10 */
        mov %ax, %ds
        mov %ax, %ss
        mov %ax, %es
        mov %ax, %fs
        mov %ax, %gs
        .byte  0xEA
        .long  done
        .word  CODE_SEL  /* CODE_SEL  equals =0x8 */
done:
        ret

Please reply soon.....

Thanks

Re: Expand down stack segment setting on x86

Posted: Wed Sep 28, 2011 7:41 am
by Combuster
If you have to post code, use

Code: Select all

 tags as per the forum rules, but right now I don't even see the relevance of code related to your question. :shock: 

Second problem: I went looking for the definition of [url=http://www.google.com/search?client=ubuntu&channel=fs&q=expand+down+segment&ie=utf-8&oe=utf-8]expand down segment[/url]s and noticed you didn't STFW either since the first link gave quite an elaborate explanation including examples.


Please follow the forum rules, they exist for a reason (your protection from bullies and moderators included).

Re: Expand down stack segment setting on x86

Posted: Wed Sep 28, 2011 8:24 am
by RajivKumarSrivastav
Thanks for the suggestion.
Expand down segment search from google did not give me the information i need. Those are theory mostly without example for stack :( . The first link explanation did not work for me :cry: .

Boot.s has the reset vector code, temp IDT, temp GDT and then jump to kernel entry after necessary initialization .
I have posted the complete code for setting the GDT inside Kernel.
I want to know the exact working combination for line :
setkgdt(3, 0x0, 0xFF, 0xFF, 0xFFFD, 0x97, 0xCF); // stack


Thanks,

Re: Expand down stack segment setting on x86

Posted: Wed Sep 28, 2011 10:33 am
by Chandra
Intel's Manual wrote:For all types of segments except expand-down data segments, the value of the limit is one less than the size (expressed in bytes) of the segment. The
processor causes a general-protection exception in any of these cases:

þ Attempt to access a memory byte at an address > limit.
þ Attempt to access a memory word at an address òlimit.
þ Attempt to access a memory doubleword at an address ò(limit-2).

For expand-down data segments, the limit has the same function but is
interpreted differently. In these cases the range of valid addresses is from
limit + 1 to either 64K or 2^(32) - 1 (4 Gbytes) depending on the B-bit. An
expand-down segment has maximum size when the limit is zero.


The expand-down feature makes it possible to expand the size of a stack by
copying it to a larger segment without needing also to update intrastack
pointers.

The limit field of descriptors for descriptor tables is used by the
processor to prevent programs from selecting a table entry outside the
descriptor table. The limit of a descriptor table identifies the last valid
byte of the last descriptor in the table. Since each descriptor is eight
bytes long, the limit value is N * 8 - 1 for a table that can contain up to
N descriptors.

Limit checking catches programming errors such as runaway subscripts and
invalid pointer calculations. Such errors are detected when they occur, so
that identification of the cause is easier. Without limit checking, such
errors could corrupt other modules; the existence of such errors would not
be discovered until later, when the corrupted module behaves incorrectly,
and when identification of the cause is difficult.


Table 6-2. Useful Combinations of E, G, and B Bits (which is unfortunately misaligned while posting. Please read the official Manual for the insight)


Case: 1 2 3 4

Expansion Direction U U D D
G-bit 0 1 0 1
B-bit X X 0 1

Lower bound is:
0 X X
LIMIT+1 X
shl(LIMIT,12,1)+1 X

Upper bound is:
LIMIT X
shl(LIMIT,12,1) X
64K-1 X
4G-1 X

Max seg size is:
64K X
64K-1 X
4G-4K X
4G X

Min seg size is:
0 X X
4K X X


shl (X, 12, 1) = shift X left by 12 bits inserting one-bits on the right
That's all the information you need.

Re: Expand down stack segment setting on x86

Posted: Wed Sep 28, 2011 10:50 am
by Chandra
rajiv123 wrote:I want to use expand down stack from address 0xffff,0000 to 0xfffe,0000 ( 64KB) in kernel mode. G (Granularity flag) bit is set to 1 for 4KB increments.

Code: Select all

void setkgdt(uint32 index, uint16 low, uint8 mid, uint8 high, uint16 limit, uint8 access, uint8 gran)

Code: Select all

setkgdt(3, 0x0, 0xFF, 0xFF, 0xFFFD, 0x97, 0xCF); // stack
That looks terribly wrong. The limit you're passing as a parameter for the stack segment is 0xFFFd. Add higher 4 bits from the granularity field (0xF) to the limit and this gives the segment limit of 0xFFFFd*1024*4Kb = 0xFFFFD000, which is obviously not what you wanted. Moreover, you're treating the fields as if it were expand-up segment. Intel's Manual says that the expand-down segment has maximum size when limit is 0. The whole segment mechanism works slightly in reverse order. Please read the Manual carefully.

Re: Expand down stack segment setting on x86

Posted: Thu Sep 29, 2011 2:30 am
by RajivKumarSrivastav
Thanks Chandra for the reply. I have already gone thruogh theory. Most links on internet will explain the Code and Data Segments descriptor settings for reset code.Theory for Expand up stack segment is same as Data Segment. But i am not getting explanation for expand down stack segment.

I understand the concept from your below reply :
For expand-down data segments, the limit has the same function but is
interpreted differently. In these cases the range of valid addresses is from
limit + 1 to either 64K or 2^(32) - 1 (4 Gbytes) depending on the B-bit. An
expand-down segment has maximum size when the limit is zero.
But i want to use small memory region out of 4GB i.e from 0xffff,0000 to 0xfffe,0000. So i want to know what shall i write in stack segment descriptor ?
Even if the below code setting did not work.

Code: Select all

setkgdt(3, 0x0, 0xFF, 0xFF, 0xFFFE, 0x97, 0xCF); // stack
Even this URL did not work- http://www.sudleyplace.com/dpmione/expanddown.html

Can you pls post some example code from reset vector till loading GDT through lgdt instruction ?
In my development environment, i have board where i can burn/program the boot and kernel binary. Its not like having flopy image, reading sectors , copying kernel for execution etc.

Thanks,

Re: Expand down stack segment setting on x86

Posted: Thu Sep 29, 2011 3:00 am
by Combuster
Can you pls post some example code from reset vector till loading GDT through lgdt instruction ?
Write your OS for you?. That's your homework.

Please learn to read and solve your own problems. You haven't even bothered to fix all the issues mentioned by Chandra.