Page 1 of 1

Multitasking

Posted: Fri Jan 09, 2009 10:04 am
by eXeCuTeR
Well, I can't get multitasking work properly.
Qemu just quits (bochs restarts...bochsout: http://pastebin.com/m48c9e5ce)
here is task_t:

Code: Select all

typedef struct task_t
{
	int pid; // task id
	unsigned int stack; // stack of the task
	unsigned char state; // is task alive?
	void (*thread_start)(void); // a pointer to the first function that will executed (eip) in the task
	struct task_t *next; // pointer to the next task
} task_t;

Code: Select all

#include "task.h"
#include "mm.h"
#include "screen.h"
#include "hardware.h"

task_t *tasks;
unsigned int tasks_num, current_pid;

void initialize_multitasking(void)
{
	tasks = (task_t *)malloc(sizeof(task_t));
	tasks_num = 0;
	unsigned int divisor = 1193180 / 50;
	outport(0x43, 0x36);
	outport(0x40, divisor & 0xFF);
	outport(0x40, (divisor >> 8) & 0xFF);
	outport(0x21, 0x00); // enable interrupts from IRQ 0-7 (PIT will now start working)
	create_task(0, idle);
}

void idle(void)
{
	puts("\nIdling...\n");
	for(;;) ;
}

void clone_task(task_t *source, task_t *dest)
{
	dest->pid = source->pid;
	dest->stack = source->stack;
	dest->state = source->state;
	dest->thread_start = source->thread_start;
	dest->next = source->next;
}

void create_task(int id, void (*thread_start)(void))
{
	asm volatile("cli"); // no one should interrupt us
	task_t *temp_task = (task_t *)malloc(sizeof(task_t));
	temp_task->pid = id;
	temp_task->next = 0;
	temp_task->thread_start = thread_start;
	temp_task->stack = (unsigned int)malloc(0x1000);
	
	unsigned int *stack = (unsigned int *)(temp_task->stack + 0x1000/*stack grows downwards*/);
	/**--stack = 0; // ss 
	*--stack = 0; // useresp*/
	
	*--stack = 0x202; // eflags
	*--stack = 0x08; // cs
	*--stack = (unsigned int)thread_start; // eip
	
	unsigned int i = 0;
	for(;i<8;i++) // pusha = 0
		*--stack = 0;
	
	for(i=0;i<4;i++) // gs, fs, es, ds
		*--stack = 0x10;
	
	temp_task->state = 1; // is avaiable
	temp_task->stack = (unsigned int)stack;
	clone_task(temp_task, &tasks[id]);
	
	current_pid = id;
	tasks_num++;
}

unsigned int schedule_tasks(unsigned int context)
{
	outport(0x20, 0x20); // it's IRQ0, we should inform the slave that we've got the message.
	return tasks[0].stack; // i just want to try 1 task for now
}

Re: Multitasking

Posted: Fri Jan 09, 2009 11:20 am
by Combuster
Try tracking your stackpointer, its broken:
ESP=ffffffff
Bochs debugger can help you with that

Re: Multitasking

Posted: Mon Jan 12, 2009 1:15 pm
by eXeCuTeR
Combuster wrote:Try tracking your stackpointer, its broken:
ESP=ffffffff
Bochs debugger can help you with that
I haven't tried the bochs debugger yet. how do I use it?

Re: Multitasking

Posted: Mon Jan 12, 2009 1:52 pm
by cyr1x
I think your problem lies in the popa(d) instruction.
eXeCuTeR wrote: unsigned int i = 0;
for(;i<8;i++) // pusha = 0
*--stack = 0;
You set everything to 0. If you execute the popa(d) instruction you overwrite esp with 0.
This is just a guess, but that is the only thing I can think of for now.

Re: Multitasking

Posted: Mon Jan 12, 2009 2:19 pm
by eXeCuTeR
cyr1x wrote:I think your problem lies in the popa(d) instruction.
eXeCuTeR wrote: unsigned int i = 0;
for(;i<8;i++) // pusha = 0
*--stack = 0;
You set everything to 0. If you execute the popa(d) instruction you overwrite esp with 0.
This is just a guess, but that is the only thing I can think of for now.
nope, this is not the problem, thanks anyways.
how do you i use the bochs debugger then guys? :P

Re: Multitasking

Posted: Tue Jan 13, 2009 7:54 am
by djsilence
HI, anyone.

I'm trying to implement multitasking. I read about software-trask switching. As I understand current eip value needs be stored and new eip value needs be loaded. I'm writing according to BrokenThorn.com tutorial, that is written in MSVC++. I tried to use that asm (ex.: _asm mov eax, eip) and got an error: eip - unknown symbol. Something like this. So, if anyone know, what need I do?

Thanks.

Re: Multitasking

Posted: Tue Jan 13, 2009 8:15 am
by giszo
djsilence wrote:I tried to use that asm (ex.: _asm mov eax, eip) and got an error: eip - unknown symbol. Something like this. So, if anyone know, what need I do?
You can't access the EIP register like any other general purpose register. I suggest you to check how interrupts are working and the IRET instruction (especially their effect on the stack) and after that you can easily figure out how you can change the value of EIP.

giszo

Re: Multitasking

Posted: Tue Jan 13, 2009 3:23 pm
by eXeCuTeR
berkus wrote:Configure bochs with debugger, and run it.

This is configure line for bochs i'm using in osdev (the last 3 lines enable the debugger among other things):

Code: Select all

  # --disable-readline is for bfe2 front-end
  ./configure --prefix=/usr --enable-vbe --without-wx --enable-cpu-level=6 \
        --enable-4meg-pages --enable-global-pages --enable-pae --enable-fpu \
        --enable-mmx --disable-3dnow --enable-sse --enable-sep \
        --enable-sb16=linux \
        --enable-iodebug --enable-debugger --enable-port-e9-hack --enable-disasm \
        --enable-x86-debugger --enable-instrumentation
As you may have guessed, there are debugger front-ends for you GUI lovers out there.
After I configure this way, and then running `make` I get:

Code: Select all

cd iodev && \
	make  libiodev.a
make[1]: Entering directory `/home/executer/Desktop/bochs-20090111/iodev'
g++ -c  -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES    devices.cc -o devices.o
../instrument/stubs/instrument.h: In member function ‘void bx_devices_c::outp(Bit16u, Bit32u, unsigned int)’:
../instrument/stubs/instrument.h:97: error: too many arguments to function ‘void bx_instr_outp(Bit16u, unsigned int)’
devices.cc:958: error: at this point in file
make[1]: *** [devices.o] Error 1
make[1]: Leaving directory `/home/executer/Desktop/bochs-20090111/iodev'
make: *** [iodev/libiodev.a] Error 2

Re: Multitasking

Posted: Tue Jan 13, 2009 3:49 pm
by JohnnyTheDon
--enable-instrumentation
Don't think you need this, I don't use it and my debugger runs fine.

Re: Multitasking

Posted: Wed Jan 14, 2009 11:46 am
by eXeCuTeR
JohnnyTheDon wrote:
--enable-instrumentation
Don't think you need this, I don't use it and my debugger runs fine.
Still no effect.. :( I'm also having a lot of warnings.
Anyways...does anyone has any idea why I'm getting this god damn page fault on 0xFFFFB00A?!

this is so weird they are 0xFFFFFFFF: (the eip is pointing to the interrupt_handler function)

Code: Select all

00108639062i[CPU  ] | EAX=ffffffdf  EBX=00000025  ECX=000002d9  EDX=ffffffff
00108639062i[CPU  ] | ESP=c0000004  EBP=00067ee0  ESI=ffffffff  EDI=ffffffff
00108639062i[CPU  ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00108639062i[CPU  ] | SEG selector     base    limit G D
00108639062i[CPU  ] | SEG sltr(index|ti|rpl)     base    limit G D
00108639062i[CPU  ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00108639062i[CPU  ] | EIP=00100e15 (00100e15)
00108639062i[CPU  ] | CR0=0xe0000011 CR1=0 CR2=0xbffffffc
00108639062i[CPU  ] | CR3=0x00000000 CR4=0x00000000
00108639062i[CPU  ] >> pushad  : 60
00108639062e[CPU  ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting

Re: Multitasking

Posted: Wed Jan 14, 2009 1:55 pm
by Combuster
CR3=0x00000000
is this valid with paging enabled?

Re: Multitasking

Posted: Wed Jan 14, 2009 3:04 pm
by eXeCuTeR
Combuster wrote:
CR3=0x00000000
is this valid with paging enabled?
Everything is just messed up somehow, that's totally weird.

Re: Multitasking

Posted: Thu Jan 15, 2009 3:31 pm
by eXeCuTeR
PLAESE HELP OUT distinguish the error in the code that causes a page faullt and messes the registers up!! =[

I also use these:

Code: Select all

global writeto_cr3
writeto_cr3:
	mov eax, [esp+4]
	mov cr3, eax
	ret
	
global or_cr0
or_cr0:
	mov eax, cr0
	or eax, 0x80000000
	mov cr0, eax
	ret

global readfrom_cr2 ; for page faults
readfrom_cr2:
	mov eax, cr2
	ret
and my current code (i just copied this code now for a tutorial because im so exhausted =[)

Code: Select all

#include "task.h"
#include "mm.h"
#include "screen.h"
#include "hardware.h"

typedef struct{        //Simple structure for a thread
  unsigned int esp0;   //Stack for kernel
  unsigned int esp3;   //Stack for process
} Thread;

Thread Threads[2];     //Space for our simple threads. Just 2!
int CurrentTask = -1;  //The thread currenlty running (-1 == none)
int first = 0;

void initialize_multitasking(void)
{
	CreateTask(0, idle);
	CreateTask(1, idle);
	unsigned int divisor = 1193180 / 50;
	outport(0x43, 0x36);
	outport(0x40, divisor & 0xFF);
	outport(0x40, (divisor >> 8) & 0xFF);
	outport(0x21, 0x00); // enable interrupts from IRQ 0-7 (PIT will now start working)
}

void idle()
{
	puts("IDLE");
	for(;;) ;
}

void idle2()
{
	puts("idle");
	for(;;) ;
}

//This will create a task
//It will make a stack that looks like it has all
//of the stuff of an IRQ handler 'pushed' on it
void CreateTask(int id, void (*thread)()){
 unsigned int *stack;
 
 Threads[id].esp0 = (unsigned int)malloc(0x1000) + 4096; //This allocates 4kb of memory, then puts the pointer at the end of it
 
 stack = (unsigned int* )Threads[id].esp0; //This makes a pointer to the stack for us
 
 //First, this stuff is pushed by the processor
 *--stack = 0;
 *--stack = 0;
 *--stack = 0x0202; //This is EFLAGS
 *--stack = 0x08;   //This is CS, our code segment
 *--stack = (unsigned int)thread; //This is EIP
 
 //Next, the stuff pushed by 'pusha'
 *--stack = 0; //EDI
 *--stack = 0; //ESI
 *--stack = 0; //EBP
 *--stack = 0; //Just an offset, no value
 *--stack = 0; //EBX
 *--stack = 0; //EDX
 *--stack = 0; //ECX
 *--stack = 0; //EAX
 
 //Now these are the data segments pushed by the IRQ handler
 *--stack = 0x10; //DS
 *--stack = 0x10; //ES
 *--stack = 0x10; //FS
 *--stack = 0x10; //GS
 
 Threads[id].esp0 = (unsigned int)stack; //Update the stack pointer
}

//Switch between our two tasks
//Notice how we get the old esp from the ASM code
//It's not a pointer, but we actually get the ESP value
//That way we can save it in our task structure
int TaskSwitch(unsigned int OldEsp){
 if(CurrentTask != -1){ //Were we even running a task?
  Threads[CurrentTask].esp0 = OldEsp; //Save the new esp for the thread
  
  //Now switch what task we're on
  if(CurrentTask == 0) CurrentTask = 1;
  else CurrentTask = 0;
 } else{
  CurrentTask = 0; //We just started multi-tasking, start with task 0
 }
 unsigned int a = Threads[CurrentTask].esp0;
 	outport(0x20, 0x20);
 	// return a;
 return OldEsp; //Return new stack pointer to ASM
}

Code: Select all

extern TaskSwitch
extern putdec
global IRQ0
IRQ0:
 	pusha
 	push ds
 	push es
 	push fs
 	push gs
 
 	mov ax, 0x10
 	mov ds, ax
 	mov es, ax
 	mov fs, ax
 	mov gs, ax
 
 	push esp
 	call TaskSwitch
 	
 	;push eax
 	;call putdec
 	;pop eax
 	
 	mov esp, eax
	
 	pop gs
 	pop fs
 	pop es
 	pop ds
 	popa
 	
 	iret

Re: Multitasking

Posted: Fri Jan 16, 2009 3:14 pm
by eXeCuTeR
Got it working finally. thanks guys!