Page 1 of 1

Triple Fault Problem

Posted: Mon Mar 24, 2008 8:43 am
by Jeko
I'm implementing software multitasking with paging. But when I switch processes there is a triple fault. If I don't switch the PDBR, there isn't the triple fault.
Maybe this is due to my setup of task's PDBRs?

If you need source to control I will post it.

Posted: Mon Mar 24, 2008 8:49 am
by AJ
Hi,

Although there could be other reasons for this, the most likely thing is that either your task, kernel, stack or PCB are not paged in to your new page directory.

Could you run the OS in Bochs and just post the final register dump here, please?

Cheers,
Adam

Posted: Mon Mar 24, 2008 8:58 am
by Jeko
00009704253d[CPU0 ] page fault for address 00000000d0001170 @ 00000000c0000c29
00009704253d[CPU0 ] exception(0x0E)
00009704253d[CPU0 ] interrupt(): vector = 14, INT = 0, EXT = 1
00009704253d[CPU0 ] int_trap_gate286(): INTERRUPT TO SAME PRIVILEGE
00009704271d[CPU0 ] MOV_RdCd: reading CR2
00009708112d[CPU0 ] IRET PROTECTED
00010260690d[CPU0 ] interrupt(): vector = 32, INT = 0, EXT = 1
00010260690d[CPU0 ] int_trap_gate286(): INTERRUPT TO SAME PRIVILEGE
00010260781d[CPU0 ] MOV_CdRd:CR3 = 01003000
00010260798d[CPU0 ] IRET PROTECTED
00010260799d[CPU0 ] page fault for address 00000000b0003ffc @ 00000000c0002b31
00010260799d[CPU0 ] exception(0x0E)
00010260799d[CPU0 ] interrupt(): vector = 14, INT = 0, EXT = 1
00010260799d[CPU0 ] interrupt(): INTERRUPT TO INNER PRIVILEGE
00010260799d[CPU0 ] page fault for address 0000000000000008 @ 00000000c0002b30
00010260799d[CPU0 ] exception(0x0E)
00010260799d[CPU0 ] interrupt(): vector = 8, INT = 0, EXT = 1
00010260799d[CPU0 ] interrupt(): INTERRUPT TO INNER PRIVILEGE
00010260799d[CPU0 ] page fault for address 0000000000000008 @ 00000000c0002b30
00010260799d[CPU0 ] exception(0x0E)
00010260799i[CPU0 ] protected mode
00010260799i[CPU0 ] CS.d_b = 32 bit
00010260799i[CPU0 ] SS.d_b = 32 bit
00010260799i[CPU0 ] EFER = 0x00000000
00010260799i[CPU0 ] | RAX=0000000000000000 RBX=0000000000000000
00010260799i[CPU0 ] | RCX=0000000000000000 RDX=0000000000000000
00010260799i[CPU0 ] | RSP=00000000b0004000 RBP=0000000000000000
00010260799i[CPU0 ] | RSI=0000000000000000 RDI=0000000000000000
00010260799i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00010260799i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00010260799i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00010260799i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00010260799i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf af pf cf
00010260799i[CPU0 ] | SEG selector base limit G D
00010260799i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00010260799i[CPU0 ] | CS:001b( 0003| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | DS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | SS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | ES:0023( 0004| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | FS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | GS:0023( 0004| 0| 3) 00000000 000fffff 1 1
00010260799i[CPU0 ] | MSR_FS_BASE:0000000000000000
00010260799i[CPU0 ] | MSR_GS_BASE:0000000000000000
00010260799i[CPU0 ] | RIP=00000000c0002b30 (00000000c0002b30)
00010260799i[CPU0 ] | CR0=0x80010011 CR1=0x0 CR2=0x0000000000000008
00010260799i[CPU0 ] | CR3=0x01003000 CR4=0x00000200
00010260799i[CPU0 ] >> push ebp : 55
00010260799p[CPU0 ] >>PANIC<< exception(): 3rd (14) exception with no resolution

Posted: Mon Mar 24, 2008 9:03 am
by Jeko
This is my code for creating a new vspace for a user task:

Code: Select all

	newtask->pdbr = (unsigned int*)kmalloc(0x1000);

	// Initialize PDBR.
	memset( newtask->pdbr, 0, PDE_INDEX(K_VIR_START) * sizeof(unsigned int) );

	//Kernel memory mapping in each task
	for( i = PDE_INDEX(K_VIR_START); i < 1023; i++ )
		newtask->pdbr[ i ] = ((unsigned int*)PAGE_DIR_MAP)[ i ];

	//Heap
	newtask->heap_start = USER_HEAP_START;
	newtask->heap_size = 0;

	//User stack
	phys_addr = pop_frame();
	newtask->pdbr[ PDE_INDEX(USER_STACK_START) ] = phys_addr | P_PRESENT | P_USER | P_WRITE;

	//Map page directory into itself.
	newtask->pdbr[ 1023 ] =  vir_to_phys((unsigned int)(newtask->pdbr)) | P_PRESENT | P_WRITE;

	//Stack initialization
	//Temporary map this page for setting some values
	map_page(KERNEL_TEMP_AREA, phys_addr, P_PRESENT | P_WRITE);

	stacksetup = (unsigned int*)KERNEL_TEMP_AREA;
	newtask->user_stack = (unsigned int*)USER_STACK_START+4096;
	stacksetup += 1024;
	*stacksetup--;
	*stacksetup = (unsigned int)end_task;

	unmap_page(KERNEL_TEMP_AREA);
EDIT!

Posted: Mon Mar 24, 2008 10:02 am
by Jeko
I switch PDBR with this code:

Code: Select all

asm("cli");
switch_mmu((unsigned int)vir_to_phys(last_task->pdbr));
asm("sti");

Posted: Mon Mar 24, 2008 12:12 pm
by Jeko
If I put this in my task's initialization code:

Code: Select all

newtask->pdbr[ 0 ] = ((unsigned int*)PAGE_DIR_MAP)[ 0 ];
The kernel works... Why???

Maybe there are somethings in my kernel that aren't higher half?

Posted: Mon Mar 24, 2008 12:32 pm
by Jeko
The kernel continues to work, but multitasking doesn't work...

There is a page fault at 0xB0000FFC (the user stack at esp3)

However I have two questions:
1 - Why I must include the lowest 4MB of memory in the task's address space?
2 - Why the ESP value of the task is setted the same as the kernel stack of the task?

Posted: Tue Mar 25, 2008 3:45 am
by Jeko
solved.

Posted: Tue Mar 25, 2008 9:04 am
by lukem95
how did you solve it? tell us :)

Posted: Tue Mar 25, 2008 3:32 pm
by Jeko
lukem95 wrote:how did you solve it? tell us :)
With this:

Code: Select all

   phys_addr = pop_frame();
   newtask->pdbr[ PDE_INDEX(USER_STACK_START) ] = phys_addr | P_PRESENT | P_USER | P_WRITE; 
I was only mapping a page directory without a page table.
With this it works perfectly:

Code: Select all

	stacksetup = (unsigned int*)pop_frame();
	map_page(KERNEL_TEMP_AREA, stacksetup, P_PRESENT | P_WRITE);

	phys_addr = pop_frame();
	newtask->pdbr[ PDE_INDEX(USER_STACK_START) ] = (unsigned int)stacksetup | P_PRESENT | P_WRITE | P_USER;
	((unsigned int*)KERNEL_TEMP_AREA)[PTE_INDEX(USER_STACK_START) ] = phys_addr | P_PRESENT | P_WRITE | P_USER;

	unmap_page(KERNEL_TEMP_AREA);