Weird Multitasking Errors

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.
K.J.

Weird Multitasking Errors

Post by K.J. »

Okay, my multitasking code is giving me some really weird errors. It occasionaly triple faults, gives a GPE, or a debug error. It is also sometime giving me this error:
[tt]00009755199p[CPU0 ] >>PANIC<< fetch_raw_descriptor: LDTR.valid=0[/tt]

The funny thing is, the error I get is random. From tests I've done, I'm guessing that the problem might be due to incorrectly setting up the stack for a new function/program.

Below is the source code....

[tt]
_irq0:
???cli
???push gs
???push fs
???push es
???push ds
???pusha

???mov eax, esp?????????; this way the _scheduler routine can get the old esp
???mov [_old_esp], eax

???mov eax, _LINEAR_DATA_SEL???; setup segment registers
???mov ds, eax
???mov es, eax
???mov eax, 0
???mov fs, eax
???mov gs, eax

???mov eax, _scheduler
???call eax????????????; call the scheduler(it's coded in C)

???mov al, 0x20
???out 0x20, al

???mov esp, [_new_esp]

???popa
???pop ds
???pop es
???pop fs
???pop gs
???sti
???iretd
[/tt]

[tt]
u_char first_time=1;

thread_struct My_Threads[1];
u_long new_esp;
u_long old_esp;

void scheduler()
{
???if(first_time == 0)
???{
??????My_Threads[ 0].esp = old_esp;
???} else
???{
??????first_time = 0;
???};
???new_esp = My_Threads[ 0].esp;
};
[/tt]

[tt]
u_short __total_num_threads=0;

void create_thread(thread_struct *new_thread, u_short process_id, u_long eip, u_long ds, u_long cs, u_long ss)
{
???u_char i;

???new_thread->id = __total_num_threads;
???__total_num_threads++;
???new_thread->process_id = process_id;
???new_thread->executing = 0;
???new_thread->sleeping = 0;

???// "push" 8 GP registers
???for(i = 0; i < 7; i++)
???{
??????new_thread->stack = 0xFFFFFFFF;
???};

???new_thread->stack[8] = ds;?????????// ds
???new_thread->stack[9] = 0x8;?????????// es
???new_thread->stack[10] = 0;?????????// fs
???new_thread->stack[11] = 0;?????????// gs

???new_thread->stack[12] = eip;?????????// eip
???new_thread->stack[13] = cs;?????????// cs
???new_thread->stack[14] = 0x200;?????????// eflags

???new_thread->stack[15] = &new_thread->stack[254];???// "old" esp
???new_thread->stack[16] = ss;?????????// ss

???new_thread->esp = &new_thread->stack[ 0];
};
[/tt]

[tt]
typedef struct {
???u_short id;??????// thread's "personal" id, assigned to it by the kernel
???u_short process_id;???// the id of the process that owns the thread

???u_long stack[255];??????// stack for this thread(1024 bytes long)
???u_long esp;??????// esp to this task's stack
} thread_struct;
[/tt]

[tt]
void task_1()
{
???for(;;)
???{
??????putc('a');
??????putc('b');
??????putc('c');
???};
};
[/tt]

The thread is created with:
[tt]create_thread(&My_Threads[ 0], 0, (u_long)&task_1, 0x08, 0x10, 0x08);[/tt]

Hopefully all that code doesn't scare off everyone. ;)

Basically, irq0 is 'installed', a thread is made, and then interrupts are enabled. The first time throught irq0, the thread is started. After that, it should just keep going. The thread does get started and works fine until another task switch though. Then one of the above mentioned errors happen.

Any help at all is appreciated,
K.J.

*hmm... I need a new avatar, everyone seems to be using yoda*
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Weird Multitasking Errors

Post by Pype.Clicker »

isn't the stack growing *downwards* ? i see you fake-pushing stuffes with stack[i++]=value ... it should be [i--], imho ...
.bdjames

Re:Weird Multitasking Errors

Post by .bdjames »

pushad, popad
.bdjames

Re:Weird Multitasking Errors

Post by .bdjames »

typedef struct {
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int dummy_esp;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
unsigned word ds;
unsigned word ds;
unsigned word es;
unsigned word fs;
unsigned word gs;
} stack;
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Weird Multitasking Errors

Post by Pype.Clicker »

.bdjames wrote: pushad, popad
in BITS32 mode, is the "d" mandatory ? i always enforce it because my first NASM version was a bit buggy (so i use popad/pushad/iretd), but what about latest release?
Whatever5k

Re:Weird Multitasking Errors

Post by Whatever5k »

pushad will *always* be a 32 Bit operation. If you use pusha (without d), it depends if you're in 16 or 32 bit mode...
So if you use 32 bit and use pusha, it'll be the same as pushad
K.J.

Re:Weird Multitasking Errors

Post by K.J. »

No, the stack grows upwards. For each push, esp gets decremented, for each pop, incremented. That's why most people setup thier stack in assembly like:

[tt]
resb 1024
stack:
[/tt]

I replaced pusha and popa with pushad and popad, it made no difference.

K.J.
Curufir

Re:Weird Multitasking Errors

Post by Curufir »

Aren't these two lines contradictory?

Code: Select all

   mov esp, [_new_esp]

   popa
Deleted my original post to clear things up.

Might have missed what you're doing, but here's what I think I see. You call the scheduler, store the old value of esp, load a new value of esp, then attempt to set up the new stack so that your popa, pop es etc instructions work out correctly and the new thread can continue. If that's wrong then sorry.

I think the problem comes in with the setting of esp on your new stack. When you popa you pop off the 8 gp registers which includes esp. At this point esp is expecting to point to the value esp would have been at before you did popa (An imaginary one in this case since you set up the stack manually) ie 32 bytes offset into the stack to account for the 8 gp registers being popped off. So if you don't set that up right then when you popa esp is pointing at the wrong place, the selectors will be poped wrong, and the iret will pop off cs and eip wrong as well. Things would probably break at that point.

Curufir
K.J.

Re:Weird Multitasking Errors

Post by K.J. »

Curufir:

I think that could be it... why the thread is able to start at all with that though I'm unsure... I'll mess around with this after skewl to day and post my findings. :)

K.J.
.bdjames

Re:Weird Multitasking Errors

Post by .bdjames »

u_long is 64 bit, so your stack is not aligned
right. The seg registers are 16bit, the general
registers are 32 bit.

new_thread->stack.ds = ds; // ds
new_thread->stack.es = 0x8; // es
new_thread->stack.fs = 0; // fs
new_thread->stack.gs = 0; // gs

new_thread->stack.eip = (void *)task_1 // eip
new_thread->stack.cs = cs; // cs
new_thread->stack.eflags = 0x200; // eflags

You have forgotten to save the flags

pushfd, popfd
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Weird Multitasking Errors

Post by Pype.Clicker »

K.J. wrote: No, the stack grows upwards. For each push, esp gets decremented, for each pop, incremented.
sorry, but what you describe - esp decremented while pushing - is definitely downard to my sense ... i mean when you push ds, the stack grows ... and the address for the stack pointer goes down in the address space ...

now, consider the following code with an initial value of esp=0x8000:

Code: Select all

push ds
push es
push gs
push fs
what you will see on the stack is ds-value at 0x8000, es-value at 0x7ffc, gs value at 0x7ff8 and fs value at 0x7ff4, right ?


and, okay, i admit despite this little lexical conflict, your code should be right 'cuz you used the POP order - not the PUSH order for your stuffes ... may the Shame be on me ... [me=Pype.Clicker]surrender.[/me]
u_long is 64 bit, so your stack is not aligned
right. The seg registers are 16bit, the general
registers are 32 bit.
unsigned long is 32 bits, long long is 64 (in GCC, at least)
And even if segment registers are 16 bits, when they are pushed, they come with a full 32 bit word (higher 16 bits are 0ed)
so your stack structure is unlikely to work

mov esp, [_new_esp]

popa
a.f.a.i.k. the ESP value from pusha is ignored by popa ...
Curufir

Re:Weird Multitasking Errors

Post by Curufir »

Pype.Clicker wrote:

mov esp, [_new_esp]

popa
a.f.a.i.k. the ESP value from pusha is ignored by popa ...
Wasn't what I meant Pype.Clicker.

What I meant is that by doing the popa he also pops off a new value of esp. Now because he sets up his stack manually this means that he has to take into account when building the stack that the esp he stores in the stack should be pointing at the location above where he builds the 8 gp registers.

Curufir
.bdjames

Re:Weird Multitasking Errors

Post by .bdjames »

K.J.

Re:Weird Multitasking Errors

Post by K.J. »

The flags are saved whenever an interrupt happens automatically by the CPU.

I replaced pushad and popa with individual push and pop statements and ended up with this code:

[tt]
void create_thread(thread_struct *new_thread, u_short process_id, u_long eip, u_long ds, u_long cs, u_long ss)
{
u_char i;

new_thread->id = __total_num_threads;
__total_num_threads++;
new_thread->process_id = process_id;
new_thread->executing = 0;
new_thread->sleeping = 0;

// "push" 7 GP registers
for(i = 0; i < 7; i++)
{
new_thread->stack = 0xFFFFFFFF;
};

new_thread->stack[8] = ds; // ds
new_thread->stack[9] = 0x8; // es
new_thread->stack[10] = 0; // fs
new_thread->stack[11] = 0; // gs

new_thread->stack[12] = eip; // eip
new_thread->stack[13] = cs; // cs
new_thread->stack[14] = 0x200; // eflags

new_thread->stack[15] = &new_thread->stack[254]; // "old" esp
new_thread->stack[16] = ss; // ss

new_thread->stack[3] = &new_thread->stack[4];

new_thread->esp = &new_thread->stack[ 0];
};

_irq0:
cli
push gs
push fs
push es
push ds

push eax
push ecx
push ebx
push edx
push esp
push edi
push esi
push ebp

mov eax, esp
mov [_old_esp], eax

mov eax, _LINEAR_DATA_SEL
mov ds, eax
mov es, eax
mov eax, 0
mov fs, eax
mov gs, eax

mov eax, _scheduler
call eax ; call the scheduler(it's coded in C)

mov al, 0x20
out 0x20, al

mov esp, [_new_esp]

pop ebp
pop esi
pop edi
pop esp
pop edx
pop ebx
pop ecx
pop eax

pop ds
pop es
pop fs
pop gs
sti
iretd
[/tt]

This code immediatly gives a GPE. The task doesn't even start at all(it did with pushad and popad). Any ideas?

K.J.
.bdjames

Re:Weird Multitasking Errors

Post by .bdjames »

int PushTestByte(){
int result;
asm ( "movl %%esp, %0\n\t" \
".byte 0x66,0x6A,0\n\t" \
"subl %%esp, %0\n\t" \
"addl %0, %%esp\n\t" \
:"=r" (result) \
);
return result;
}

int PushTestWord(){
int result;
asm ( "movl %%esp, %0\n\t" \
"pushw %%ds\n\t" \
"subl %%esp, %0\n\t" \
"addl %0, %%esp\n\t" \
:"=r" (result) \
);
return result;
}

int PushTestDWord(){
int result;
asm ( "movl %%esp, %0\n\t" \
"pushl %%eax\n\t" \
"subl %%esp, %0\n\t" \
"addl %0, %%esp\n\t" \
:"=r" (result) \
);
return result;
}

int main(){
printf("A byte takes %i bytes on the stack\n",PushTestByte());
printf("A word takes %i bytes on the stack\n",PushTestWord());
printf("A dword takes %i bytes on the stack\n",PushTestDWord());
return 0;
}






E:\DOCUME~1\ADMINI~1\Desktop\NEWFOL~2>gcc test.c

E:\DOCUME~1\ADMINI~1\Desktop\NEWFOL~2>a
A byte takes 2 bytes on the stack
A word takes 2 bytes on the stack
A dword takes 4 bytes on the stack
Post Reply