Page 2 of 3

Posted: Tue Jan 22, 2008 5:50 pm
by t0xic
Lukem, I used dir->tablesPhysical (Thats whats in his paging code)

Posted: Wed Jan 23, 2008 2:21 am
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!

Posted: Wed Jan 23, 2008 7:23 am
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 :)

Posted: Wed Jan 23, 2008 9:47 am
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

Posted: Wed Jan 23, 2008 9:52 am
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

Posted: Wed Jan 23, 2008 12:38 pm
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]

Posted: Sat Jan 26, 2008 5:35 am
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. :(

Posted: Sat Feb 02, 2008 9:52 am
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.

Posted: Sat Feb 02, 2008 10:35 pm
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 :)

Posted: Sun Feb 03, 2008 6:54 am
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?

Posted: Tue Feb 26, 2008 10:55 am
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

Posted: Tue Feb 26, 2008 11:05 am
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! :)

Posted: Tue Feb 26, 2008 11:44 am
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 :)

Posted: Tue Feb 26, 2008 2:38 pm
by t0xic
Meh, I just completely scrapped JamesM's code until the tutorial (no offense to you or your code) :D

Posted: Wed Feb 27, 2008 9:23 am
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