Stack problem

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
Anton80
Posts: 2
Joined: Sat Aug 11, 2007 11:10 am

Stack problem

Post by Anton80 »

I'm writing freestanding code for my OS experiment, and i have a problem that i cannot resolve.
Initialy I had kernel stack segment selector same as data segment, and now Im trying to separate it.
The boot plan is the folowing:
1. boot sector is loading some amount of sectors from disk which are the loader code
2. loader code switches to protected mode and have functions to access full memory, DMA etc. It operates with 2 selectors at all (code and data).
3. loader code loads the main kernel, with no space limitations.
I had allocated new selector in gdt and trying to set stack before entering the BIG kernel with the folowing code(AT&T asm syntax):

void k_setup_stack(void *ret_address)
{
k_pmode_gdt_init();

asm("
cli
mov %%edx,%%esp
mov %%edx,%%ebp
mov %%ax,%%ss

ljmp $8,$nxt
nop
nxt:
mov %%ax,%%ss // another try
mov %%edx,%%esp
mov %%edx,%%ebp

sti
// trying to push
push %%eax
push %%eax
push %%eax
push %%eax
s: jmp s //////////////////////////////////////////////////////////////////
ret

:
: "a"(KERNEL_STACK_SELECTOR),
"d"(KERNEL_STACK_SIZE),
"c"(ret_address)
);
k_panic("stop");


}

, but the CPU behavior is some kind bogus.
The results I have at point "s: jmp s".
Bochs cpu dump:
eax:0x0010000f, ebx:0x00000000, ecx:0x0010000f, edx:0x00001000
ebp:0x00001000, esp:0x00000ff0, esi:0x00007c52, edi:0x0000ffde
eip:0x00100c52, eflags:0x00000202, inhibit_mask:0
cs:s=0x0008, dl=0x0000ffff, dh=0x00cf9a00, valid=1
ss:s=0x0018, dl=0x40001000, dh=0x00c09312, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9200, valid=7
es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0x00121000, limit=0x3f
idtr:base=0x00120000, limit=0x7ff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000011, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000

Stack values:
<bochs:3> print-stack
Stack address size 4
| STACK 0x00000ff0 [0x00000000]
| STACK 0x00000ff4 [0x00000000]
| STACK 0x00000ff8 [0x00000000]
| STACK 0x00000ffc [0x00000000]
| STACK 0x00001000 [0x000003e9]
| STACK 0x00001004 [0x01b40001]
| STACK 0x00001008 [0x10cd20b5]
| STACK 0x0000100c [0xa27c03a0]
| STACK 0x00001010 [0x010f1003]
| STACK 0x00001014 [0xe4107716]
| STACK 0x00001018 [0xe6020c92]
| STACK 0x0000101c [0xc0200f92]
| STACK 0x00001020 [0x220f010c]
| STACK 0x00001024 [0x102aeac0]
| STACK 0x00001028 [0x66fa0008]
| STACK 0x0000102c [0x8e0010b8]
<bochs:4>
there are zeroes in the stack which resulted by my pushes... I cannot undestand what is going wrong. This is the main question.

And the other question is about the whole idea in general. I see no limitations from C compiler of having separate stack segment to run stack safely. Windows puts stacks after disabled memory page but in that case you have a page fault, in which the CPU pushes error code to the stack, so double fault is triggered (etc) and cpu reboots.

I will be very gratefull of help.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

Bochs manual wrote:print-stack [num words]

Print the num words top 16-bit words on the stack. Num words defaults to 16. Only works reliably in protected mode when the base address of the stack segment is zero.
As for your other question, I don't think modern Windows is quite dumb enough to allow page faults to go unhandled and result in a double fault, which also goes unhandled and so triple fault and reset. The stack in Windows (and also my os) is protected by a/some padding page(s) which are set not present. If an application overflows the stack and triggers a page fault, it can either cause the stack to be extended downwards (never upwards though) or cause a process exception which usually results in the termination of the process, if the stack has already reached its maximum limit.

Personally I would recommend against using a separate segment for the stack; use a flat memory model with null, code0, data0, code3, data3 and tss as your gdt entries and you shouldn't go far wrong. For one it is more portable. Also, I cannot guarantee (although someone else might be able to) that gcc does not output code which references data with respect to the stack pointer (or more likely ebp) with instructions that do not assume ss as the default segment. e.g. something like:

Code: Select all

push ebp
mov ebp, esp
mov edx, ebp
add edx, 8
mov eax, [edx]
where this assumes edx is ebp+8 in segment ds, which in your design it wouldn't be. Although this is obviously a very contrived example.

Regards,
John.
Anton80
Posts: 2
Joined: Sat Aug 11, 2007 11:10 am

Post by Anton80 »

This sounds like well documented bochs bug.
I've already found some clues to the problem since push 5; pop eax magicaly worked. Thats when I've thought about "dump ram" feature for bochs. ;)
I have page fault handler installed as all of them 0x0-0x13 as described in P6 manual, but when i tested stack overrun i had 3rd exception without resolution. My first thought was about errorcode.
Portability is not an issue for me, so I'll try doing things in the correct way, than all other. :)
Big thanks.
Post Reply