Page 1 of 1

how to sepatate data, code, and stack segment in the GDT ?

Posted: Wed Sep 22, 2004 6:44 am
by aladdin
I want to have distinct entries for code, data and stack in my GDT, so I proceed like this :

Code: Select all

void init_gdt(void) {

  struct gdtdesc kcode, kdata, kstack, tcode, tdata, text;


  /* initialising segment descriptors*/

  //0x8 Code 
  init_code_desc(0x0, 0xFFFFF, &kcode);    //kernel Code segement 0 --> 1 Go
  //0x10 Data 
  init_data_desc(0x0, 0xFFFFF, &kdata);    //kernel data segment 0 --> 1 Go



  //0x18 kernel Stack 
  init_gdt_desc(0, 0x10, PRESENT|S|T_STACK, GRANULARITY|D|AVAILABLE, &kstack);

  //0x20 video seg
  init_gdt_desc(0xB8000, 0xFFFF, 0x92|0x60, 0x0D, &text);

  //0x28 task code
  init_gdt_desc(0x0, 0xFFFFF, 0x9a, GRANULARITY|D, &tcode);
  //0x30 task data
  init_gdt_desc(0x0, 0xFFFFF, 0x92, GRANULARITY|D, &tdata);


  //adding entries
  add_gdt_desc(kcode);
  add_gdt_desc(kdata);
  add_gdt_desc(kstack);
  add_gdt_desc(text);
  add_gdt_desc(tcode);
  add_gdt_desc(tdata);


  kgdtr.limite = GDTSIZE*8;
  kgdtr.base = GDTBASE;
  ...

then I load my GDT ...

Code: Select all

  asm("lgdtl (kgdtr)");

  asm(" movw $0x10,%ax  \n \
                movw %ax, %ds   \n \
                movw %ax, %es   \n \
                movw %ax, %fs   \n \
                movw %ax, %gs   \n \
                movw $0x18,%ax  \n \
                movw %ax, %ss   \n \
                movl $0x1FFFF,%esp      \n \
                nop     \n \
                nop     \n \
                ljmp $0x08,$next        \n \
                next:   \n");
all this works well but the problem is that I cant have more than 0x10 in stack limit
when I do this

Code: Select all

  //0x18 kernel Stack 
  init_gdt_desc(0, 0xFFFFF, PRESENT|S|T_STACK, GRANULARITY|D|AVAILABLE, &kstack);
bochs crash width the folowwing message
00017286841p[CPU ] >>PANIC<< LEAVE: BP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].limit
00017286841i[SYS ] Last time is 17
00017286841i[XGUI ] Exit.
00017286841i[CPU ] protected mode
00017286841i[CPU ] CS.d_b = 32 bit
00017286841i[CPU ] SS.d_b = 32 bit
00017286841i[CPU ] | EAX=00000018 EBX=001083bc ECX=00080800 EDX=00cf9200
00017286841i[CPU ] | ESP=0001ffff EBP=0009efdc ESI=000093bc EDI=00000000
00017286841i[CPU ] | IOPL=0 NV UP DI PL NZ AC PE NC
00017286841i[CPU ] | SEG selector base limit G D
00017286841i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00017286841i[CPU ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00017286841i[CPU ] | ES:0010( 0002| 0| 0) 00000000 000fffff 1 1
00017286841i[CPU ] | FS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00017286841i[CPU ] | GS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00017286841i[CPU ] | SS:0018( 0003| 0| 0) 00000000 0000ffff 1 1
00017286841i[CPU ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00017286841i[CPU ] | EIP=001006ec (001006eb)
00017286841i[CPU ] | CR0=0x60000011 CR1=0x00000000 CR2=0x00000000
00017286841i[CPU ] | CR3=0x00000000 CR4=0x00000000
00017286841i[ ] restoring default signal behavior

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Wed Sep 22, 2004 8:26 am
by Neuromancer
IMHO and IIRC, when you reference the EBP register, the default segment used is SS, not DS so:
mov eax, [ebp]
is just like:
mov eax, [ss:ebp]
not:
mov eax, [ds:ebp]

The C compiler in the function prolog uses:
push ebp
mov esp, ebp

And the local variables are referenced using EBP, so you should make sure that the EBP value is in the 0x00000 - 0x10FFF range.
Try setting those registers outside the C code (in the start.asm or whatever is called).

Also note that esp cannot be loaded with 0x1FFFF but max 0x10FFF (look at the assembly part of your code)

Greetings.

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Wed Sep 22, 2004 8:44 am
by aladdin
everything works well when i use the data segment for stack
but the problem occure when i attemp to use a separate stack segment :
this code loads ss with 0xFFFFF

Code: Select all

  asm(" movw $0x10,%ax  \n \
                movw %ax, %ds   \n \
                movw %ax, %es   \n \
                movw %ax, %fs   \n \
                movw %ax, %gs   \n \
                movw %ax, %ss   \n \
                movl $0x10FFF,%esp      \n \
                nop     \n \
                nop     \n \
                ljmp $0x08,$next        \n \
                next:   \n");
but this one crash :

Code: Select all

  asm(" movw $0x10,%ax  \n \
                movw %ax, %ds   \n \
                movw %ax, %es   \n \
                movw %ax, %fs   \n \
                movw %ax, %gs   \n \

movw $0x18,%ax  \n \
                movw %ax, %ss   \n \
                movl $0x10FFF,%esp      \n \
                nop     \n \
                nop     \n \
                ljmp $0x08,$next        \n \
                next:   \n");
i want to have a stack segment that that begins at 0x0 and have a 0xFFFFF limit
as defined bellow

Code: Select all

  //entry ==0x18 kernel Stack
  init_gdt_desc(0, 0xFFFFF, PRESENT|S|T_STACK, GRANULARITY|D|AVAILABLE, &kstack);

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Wed Sep 22, 2004 9:06 am
by Pype.Clicker
honestly, *i* would avoid to manipulate the stack from some C code. It would be better if you could stay on the current stack and set a different stack with some form of "control passing" to another thread.

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Wed Sep 22, 2004 9:14 am
by aladdin
ok ;)

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Thu Sep 23, 2004 9:00 am
by Neuromancer
The trick works using the data descriptor in the SS segment because it's limit are 0x00000000 - 0xFFFFFFFF, but the problem comes when your stack limits are 0x00000000 - 0x00010FFF and the C code tries to reference a SS:EBP outside this limit.
IMHO you should try to step with a debugger each assembly instruction after the 'mov ss, ax' and you'll see that the exception comes when EBP is referenced.

Greetings.

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Fri Sep 24, 2004 2:33 am
by aladdin
So the only solution is to use data segment ?

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Fri Sep 24, 2004 6:29 am
by Pype.Clicker
not necessarily. you *can* define a new stack that will have 0-X as limit -- or better, Y-0xffffffff using expand-down segment -- but you have to make sure your modification keeps consistent with the addressing so far.

Your stack here was at 0x9xxxx. If you want to change the stack segment parameters, you should better ensure that
- the base remains the same
- the new limit contains the current stack.

As a general rule, for C code, you *have* to set SS.base == DS.base because the compiler may pass references to stack-located object (and code that will use those reference has no hints about the fact the object is stack-located so it cannot use SS: override prefix as pure ASM code would have done)

Second, remapping pages and fixing EBP/ESP values will not be enough, as there is a chain of EBP values on the stack, references to stack variables etc. So the cleanest way to do this is to "fork" a new thread that will have an empty stack (or assume that the function that switches the current stack parameters will never return)

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Fri Sep 24, 2004 7:58 am
by Neuromancer
If I were you (and as I did in my OS), I would hard code those GDT values in the GDT tables, lgdt it in the start.asm (IOW the entry point) and then setup the segments AND stack. Once done, I'd call the C kernel main();

Re:how to sepatate data, code, and stack segment in the GDT

Posted: Sun Sep 26, 2004 3:00 am
by Candy
Modifying the stack from C code isn't impossible or hard even.

There's just one catch. The previous stack pointer will be restored from the base pointers, and pointers may exist to stack-bound things in a higher level function. Result is that you can only add a new stack and switch to it in lower functions.

The same limit exists in assembly, but since you have full control over what's on the stack you don't place anything on it in the first place. In the second place, you don't return by using the stack in asm either, since you know that's not done (you just got a new stack). In C this isn't obvious so you have to pay attention to the details.

There's no reason why you can't make everything in C with a little bit of inline asm. The only danger is that you get more inline asm than C code :)