Software Multitasking

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.
User avatar
t0xic
Member
Member
Posts: 216
Joined: Sat May 05, 2007 3:16 pm
Location: VA
Contact:

Post by t0xic »

Lukem, I used dir->tablesPhysical (Thats whats in his paging code)
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Hi Lukem,

Could you please post some code? When exactly does the computer hang? Does bochs tell you *where* it hangs? How do you set up current_directory?

Cheers,

James

*PS: I haven't started the documentation just as yet, I have a million and one things to do atm, and haven't been able to get round to it! It'll get done eventually though!
User avatar
razor-x
Posts: 6
Joined: Fri Jan 26, 2007 12:53 pm
Location: 's-Gravendeel - The Netherlands

Post by razor-x »

Mine is working now.. :) I used almost the same code JamesM posted earlyer:

Code: Select all

void start_task(void (*func)(void*), void *arg) 
{ 
  if (fork() == 0) 
  { 
    func(arg); 
    kill_task(); 
    for(;;); 
  } 
}
I'm at work right now, but if someone wants it, i can post the source here :)
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

sure, i set it up the same as you in paging.c

Code: Select all

printf("cloning directory:\n");
   #endif
   
   current_directory = clone_directory(kernel_directory);
   
   #ifdef DEBUG
   printf("cloning directory...ok!\n");
   printf("switching to current_directory...");
   #endif
   
   #ifdef DEBUG
   printf("updating cr3...");
   #endif
   
   /* This line is where it hangs */
    __asm__ __volatile__("mov %0, %%cr3":: "r"(current_directory->tablesPhysical));
    
   #ifdef DEBUG
   printf("ok!\n");
   #endif
    
    unsigned int cr0;
    __asm__ __volatile__("mov %%cr0, %0": "=r"(cr0));
    cr0 |= 0x80000000; // Enable paging!
    __asm__ __volatile__("mov %0, %%cr0":: "r"(cr0));
   
   #ifdef DEBUG
   printf("ok!\n");
   #endif

I took it out of the function so that i could analyse it line-by-line to see exactly where it was hanging.

Bochs reboots when i executes this, bochs dbg build pauses. I get this from the log file:

Code: Select all

00026255628i[CPU0 ] protected mode
00026255628i[CPU0 ] CS.d_b = 32 bit
00026255628i[CPU0 ] SS.d_b = 32 bit
00026255628i[CPU0 ] | EAX=c0083000  EBX=00245000  ECX=000003d4  EDX=000003d5
00026255628i[CPU0 ] | ESP=00138e68  EBP=00101fbe  ESI=00000012  EDI=0013f000
00026255628i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf SF zf af PF cf
00026255628i[CPU0 ] | SEG selector     base    limit G D
00026255628i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00026255628i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00026255628i[CPU0 ] | EIP=001024a9 (001024a9)
00026255628i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x0013a070
00026255628i[CPU0 ] | CR3=0xc0083000 CR4=0x00000000
00026255628i[CPU0 ] >> push 0x0000000f : 6A0F
00026255628e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
00026255628i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00026255628i[APIC0] local apic in CPU 0 initializing
00026255628e[CPU0 ] CPU_LOOP bx_guard.interrupt_requested=1
according to that CR3 is never being filled with the correct tablesPhysical value, as i dump this in the debugging screen. My OS reports it as: 0xc024b000
Attachments
Debugging printf's
Debugging printf's
mutlitaskingerrorz.jpg (71.85 KiB) Viewed 2235 times
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Hi,

Some food for thought:

CR3, is, as you may have guessed, a *physical* address. Therefore addresses like (both) 0xc0083000 and 0xc024b000 are both really quite wrong (unless bochs is emulating ~3GB of RAM!!).

That's because you used the address of tablesPhysical. tablesPhysical is an array that exists in virtual memory that details how the page tables exist in physical memory. current_directory->physicalAddr should give the physical address of tablesPhysical, so that is what should be loaded into cr3!

If that's still not working, could you post your modified code and also the clone_directory function if you have made any changes at all.

Cheers,

James
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

ah, that makes perfect sense.

one of these days i hope to get out of the noobdom that lets these things slip by me.

i havn't changed the clone_directory code no, i have only ported everything so far, as theres no point fiddling until it works huh?

However the address i have was from this (clone_directory()):

Code: Select all

    // Get the offset of tablesPhysical from the start of the page_directory_t structure.
    unsigned int offset = (unsigned int)dir->tablesPhysical - (unsigned int)dir;

    // Then the physical address of dir->tablesPhysical is:
    dir->physicalAddr = phys + offset;
    
    #ifdef DEBUG
     printf("Physical address: 0x%x\n",dir->physicalAddr);
    #endif
So surely that should've given an accurate physical location, not something around the 3 gig mark.

EDIT: i have gotten what i believe to be the actual address of the directory by prefixing phys with &, this gives me: 0x13ce50

but this still hangs in exactly the same place =\[/code]
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

I still have no idea what is going wrong here, iv seperated out each individual part of the process and debugged and analysed exactly whats going on, and i havn't made any progress.

All i know is that it hangs when you try to switch to the current_directory.

also... at one point it adds:

Code: Select all

unsigned int offset = (unsigned int)current_directory->tablesPhysical - (unsigned int)current_directory;
getting 0x67d40 + 0x1000. This should surely be 0x8d40? it gives 0x6bd40.

i have tried hardcoding this but it makes no difference, still hangs. so i have no idea what the problem is. :(
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

i finally got it working, it took a lot of rejigging my kernel, but its very easy to customise, and im implementing my second scheduler now.

I was wondering if anybody has a link to some information on virtual8086 tasks using software multitasking?

Also, on a slightly different note, how do people stop user programs accessing hardwear directly, or stop it executing say CLI, as then my multitasking would die.
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
ucosty
Member
Member
Posts: 271
Joined: Tue Aug 08, 2006 7:43 am
Location: Sydney, Australia

Post by ucosty »

lukem_95 wrote:Also, on a slightly different note, how do people stop user programs accessing hardwear directly, or stop it executing say CLI, as then my multitasking would die.
That would be processor ring levels. Load your apps in Ring 3 and you won't have that problem :)
The cake is a lie | rackbits.com
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

ah, i actually knew that... funny how things don't quite "align" correctly in your head sometimes isn't it. The funny thing is that my apps are already in ring 3 =\

thankyou for the fast response though :)

anybody for software-switching v86?
~ Lukem95 [ Cake ]
Release: 0.08b
Image
thomasloven
Member
Member
Posts: 89
Joined: Tue Feb 26, 2008 10:47 am
Location: Sweden

Post by thomasloven »

I get someting simmilar to razor-x error.
The tasks switch allright and I can call other functions after switching, but when I try to return from the fork() function, the child process generates a fault.
Any ideas?

I don't have my code here, right now, nor the actual error, but I'll post it as soon as I get home.

/Thomas
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

I don't have my code here, right now, nor the actual error, but I'll post it as soon as I get home.
Both of those would be useful! :)
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

well there has been a solution to this posted already, and i can assure you it works fine.

Writing your own kill_task() function may take a bit of work though

good luck :)
~ Lukem95 [ Cake ]
Release: 0.08b
Image
User avatar
t0xic
Member
Member
Posts: 216
Joined: Sat May 05, 2007 3:16 pm
Location: VA
Contact:

Post by t0xic »

Meh, I just completely scrapped JamesM's code until the tutorial (no offense to you or your code) :D
thomasloven
Member
Member
Posts: 89
Joined: Tue Feb 26, 2008 10:47 am
Location: Sweden

Post by thomasloven »

Sorry for not having this before.

Here is my code for switching task and fork-ing.

Code: Select all

void switch_task()
{
	k_puts("Switching");
		if (!current_task)
		return;

	
	unsigned int esp, ebp, eip;
	asm volatile("mov %%esp, %0" : "=r" (esp));
	asm volatile("mov %%ebp, %0" : "=r" (ebp));
	
	eip = read_eip();
	if (eip == 0x12345)
	{
		return;
	}	
	current_task->eip = eip;
	current_task->esp = esp;
	current_task->ebp = ebp;
	
	current_task = current_task->next;
	if (!current_task) current_task = ready_queue;
	eip = current_task->eip;
	esp = current_task->esp;
	ebp = current_task->ebp;
	current_directory = current_task->page_directory;
	
	asm volatile("cli");
	asm volatile("	\
	mov %0, %%ecx;	\
	mov %1, %%esp; \
	mov %2, %%ebp;	\
	mov $0x12345, %%eax;	\
	jmp *%%ecx;		" : : "r" (eip), "r"(esp), "r"(ebp));
	switch_page_directory(current_directory);
	asm volatile("sti");
/**/
}

int fork()
{
	asm volatile("cli");
	
	task_t *parent_task = (task_t*)current_task;
	
	page_directory_t *directory = clone_directory(current_directory);
	
	task_t *new_task = (task_t*)kmalloc(sizeof(task_t));
	
	new_task->id = next_pid++;
	new_task->esp = new_task->ebp = 0;
	new_task->eip = 0;
	new_task->page_directory = directory;
	new_task->next = 0;
	task_t *tmp_task = (task_t*)ready_queue;
	while(tmp_task->next)
		tmp_task = tmp_task->next;
	tmp_task->next = new_task;
	
	unsigned int eip = read_eip();
	unsigned int esp; asm volatile("mov %%esp, %0" : "=r" (esp));
		unsigned int ebp; asm volatile("mov %%ebp, %0" : "=r" (ebp));
	if (current_task == parent_task)
	{
		
		new_task->esp = esp;
		new_task->ebp = ebp;
		new_task->eip = eip;
		asm volatile("sti");
		
	
		return new_task->id;
	} else {
	k_printf("!-returning!",cursor_y, cursor_x);
	return 0;
	}
}

And here is how it is called from main.

Code: Select all

if (fork()== 0)
	{
	k_puts("FORKED!");
			for(;;);
	}
It prints the "!-returning" message, but then it stops with a page fault at 0xE040DC0C with EIP 0x1F82. Neither of which has anything to do with anything I am doing.

To me it doesn't realy seem like the problem lukem_95 was having.
Note also that even using the same page table for both processes (not changeing it) gives the same error.

/Thomas
Post Reply