[Solved] Paging problem + GPFs

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.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

[Solved] Paging problem + GPFs

Post by White-spirit »

Hello all,

I've read the Osdev wiki article about paging, so I've written a little code to activate it, but after activating it ( by or-ing CR0 with 0x80000000 ), Bochs says ">> (invalid) : FFFF" ... :?

Here's the code( I'm not sure the page tables initialization is correct... ) :

Code: Select all

#include "paging.h"

u32int page_dir[1024];
u32int page_table[1048576];

void init_pagedir(){
	int i = 0;
	for( i = 0; i <= 1024; i++ ){
		page_dir[i] ^= page_dir[i];
		page_dir[i] = page_table + 1024 * i;
		page_dir[i] = page_dir[i] >> 12;
		page_dir[i] = page_dir[i] << 12;
		page_dir[i] = page_dir[i] | 3;
	}
}

void init_pagetable(){
	int i = 0;
	for( i = 0; i < 1048576; i++ ){
		page_table[i] ^= page_table[i];
		page_table[i] = i*4096;
		page_table[i] = page_table[i] | 3;
	}
}

void load_pagedir(){
	asm volatile ("\
	movl %0, %%eax; \
	movl %%eax, %%cr3; \
	" :: "r" (page_dir));
}

void activate_paging(){
	asm volatile ("\
	movl %cr0, %eax; \
	or $0x80000000, %eax; \
	movl %eax, %cr0 \
	");
}

void init_paging(){
	printf("[DEBUG] activate_paging is located at 0x8:%h ( %d )\n", &activate_paging, &activate_paging);
	init_pagedir();
	init_pagetable();
	printf("\n *Loading page directory...");
	load_pagedir();
	printf("[DONE]");
	printf("\n *Activating paging...");
	activate_paging();
	printf("[DONE]");
	printf("\n *Paging is...");
}
I've debugged with Bochs but it doesn't help me much ( it's probably because I'm not familiar with Bochs :( ) but I've seen that it reboots after "movl %eax, %cr0" .

I wrote this code with the feet? :oops:

I personally don't understand all the paging articles I've read on JamesM's kernel development tutorials, Brokenthorn tutorials, the Osdev wiki, and SOS's tutorial... SOS uses complicated macros so it doesn't help me much, it's because I'm dumb or maybe not ready for this subject ...

Thanks :-)
Last edited by White-spirit on Mon May 12, 2008 11:21 am, edited 1 time in total.
Working on multi-tasking support ...
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

First off, why are you ^=, then =... why set it to zero if you're just going to set it in the next line anyways?

Second, please try to avoid arithmetric functions on pointers.. I would change:

Code: Select all

page_dir[i] = page_table + 1024 * i;
to

Code: Select all

page_dir[i] = &page_table[i*1024];
An easier way would be something like this however:

Code: Select all


u32int page_dir[1024]; 
u32int page_table[1024][1024]; //1024*1024 is more obvious to me

void InitTables(void)
{
   u32int Ctr,Ct2, Addr=0;
   for (Ctr=0;Ctr!=1024;++Ctr) //Page directory
   {
      for (Ct2=0;Ct2!=1024;++Ctr) //Each page table
      {
         page_table[Ctr][Ct2] = Addr;  //Set to next address
         Addr += 4096;
      }
      page_dir[Ctr] = &page_table[Ctr][0] | 3; //Set this
   }
}

Also, make suer your page_dir and page_table are page aligned (4096 bytes), if they're not, and you are doing >>12, <<12 you may be writing over memory that you don't want to be. Also, never do <= 1024... that means it will go from 0 > 1024 (including 1024!), which will over-run your page_dir, since element 1024 would be invalid memory.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Thanks for your help, and yes, it's < not <= .
I've used your code but it still doesn't work :/

Also, I've changed it a little but it's also the same :s :

Code: Select all

#define log2ph(x) (((void*)(x))+0x40000000)
#define ph2log(x) (((void*)(x))-0x40000000)

u32int page_dir[1024];
u32int page_table[1024][1024];

void init_tables(){
	int i,j;
	int ph_address = 0;
	ph_address = log2ph(ph_address);
	for( i = 0; i < 1024; i++ ){
		for( j = 0; j < 1024; j++){
			page_table[i][j] = ph_address;
			page_table[i][j] = page_table[i][j] | 3;
			ph_address += 4096;
		}
	page_dir[i] = &page_table[i][0];
	page_dir[i] |= 3;
	}
}
Working on multi-tasking support ...
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Make sure page_dir and page_table are both page aligned. Also, a print out of the bochs output may be helpful, as well as displaying the value of page_dir and page_table to see where the problem may lie. Juts out of curiousity, why are you doing log2ph and ph2log? Where are you linking your kernel? Take out the log2ph, you want to set the physical address = 0 at the start, to map the entire memory range. Unless you're trying to make your kernel look like it's at 0x00000000, there is no reason for this. And it will mess it up if you don't location the part of the kernel after paging is enabled to be 0x00000000. So the return from your set CR3 call will crash because it is trying to read the stack and from the wrong place (since everything is shifted by 1gb). Try it without that function (macro) and let us know, also post other information I asked and I'll continue helping.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Thanks.
But what means "page aligned" ? Sorry but I'm not a native english speaker ^^"
Here's the Bochs log :

Code: Select all

00000003572i[BIOS ] $Revision: 1.193 $ $Date: 2007/12/20 18:12:11 $
00000080000e[VGA  ] character height = 1, skipping text update
00000160000e[VGA  ] character height = 1, skipping text update
00000240000e[VGA  ] character height = 1, skipping text update
00000317073i[KBD  ] reset-disable command received
00000320000e[VGA  ] character height = 1, skipping text update
00000351651i[BIOS ] Starting rombios32
00000352363i[BIOS ] ram_size=0x02000000
00000372784i[BIOS ] Found 1 cpu(s)
00000400000e[VGA  ] character height = 1, skipping text update
00000480000e[VGA  ] character height = 1, skipping text update
00000560000e[VGA  ] character height = 1, skipping text update
00000640000e[VGA  ] character height = 1, skipping text update
00000662092i[VBIOS] VGABios $Id: vgabios.c,v 1.66 2006/07/10 07:47:51 vruppert Exp $
00000662163i[VGA  ] VBE known Display Interface b0c0
00000662195i[VGA  ] VBE known Display Interface b0c4
00000665120i[VBIOS] VBE Bios $Id: vbe.c,v 1.58 2006/08/19 09:39:43 vruppert Exp $
00000800000i[XGUI ] charmap update. Font Height is 16
00001109360i[BIOS ] Booting from 0000:7c00
00006486695i[BIOS ] int13_harddisk: function 41, unmapped device for ELDL=80
00006491498i[BIOS ] int13_harddisk: function 08, unmapped device for ELDL=80
00006496157i[BIOS ] *** int 15h function AX=00c0, BX=0000 not yet supported!
00071430371i[CPU0 ] CPU is in protected mode (active)
00071430371i[CPU0 ] CS.d_b = 32 bit
00071430371i[CPU0 ] SS.d_b = 32 bit
00071430371i[CPU0 ] EFER   = 0x00000000
00071430371i[CPU0 ] | RAX=00000000ffffffff  RBX=000000000002d000
00071430371i[CPU0 ] | RCX=00000000000003ff  RDX=000000000000002e
00071430371i[CPU0 ] | RSP=0000000000106e08  RBP=00000000001072b0
00071430371i[CPU0 ] | RSI=0000000000053c8e  RDI=0000000000053c8f
00071430371i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00071430371i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00071430371i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00071430371i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00071430371i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af pf cf
00071430371i[CPU0 ] | SEG selector     base    limit G D
00071430371i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00071430371i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071430371i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00071430371i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00071430371i[CPU0 ] | RIP=00000000c7538168 (00000000c7538168)
00071430371i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000000
00071430371i[CPU0 ] | CR3=0x00508c80 CR4=0x00000000
00071430371i[CPU0 ] >> (invalid)  : FFFF
00071430371e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00071430371i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called
00071430371i[CPU0 ] cpu software reset
00071430371i[APIC0] local apic in CPU 0 initializing
Next at t=71430371
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b         ; ea5be000f0
But when I use this ( because CR3 needs the physical address ) :

Code: Select all

void load_pagedir(){
	asm volatile ("\
	movl %0, %%eax; \
	movl %%eax, %%cr3; \
	" :: "r" (log2ph(page_dir)));
}
instead of this :

Code: Select all

void load_pagedir(){
	asm volatile ("\
	movl %0, %%eax; \
	movl %%eax, %%cr3; \
	" :: "r" (page_dir));
}
I get another error message :

Code: Select all

00071406647i[CPU0 ] CPU is in protected mode (active)
00071406647i[CPU0 ] CS.d_b = 32 bit
00071406647i[CPU0 ] SS.d_b = 32 bit
00071406647i[CPU0 ] EFER   = 0x00000000
00071406647i[CPU0 ] | RAX=0000000080000011  RBX=000000000002d000
00071406647i[CPU0 ] | RCX=00000000000003ff  RDX=000000000000002e
00071406647i[CPU0 ] | RSP=00000000001072b0  RBP=00000000001072b0
00071406647i[CPU0 ] | RSI=0000000000053c8e  RDI=0000000000053c8f
00071406647i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00071406647i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00071406647i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00071406647i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00071406647i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00071406647i[CPU0 ] | SEG selector     base    limit G D
00071406647i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00071406647i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00071406647i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00071406647i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00071406647i[CPU0 ] | RIP=000000000010146f (000000000010146f)
00071406647i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000040
00071406647i[CPU0 ] | CR3=0x40508c80 CR4=0x00000000
00071406647i[CPU0 ] >> or byte ptr ds:[eax], cl : 0808
00071406647e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
I'ill continue debugging ...

Thanks :-)
Working on multi-tasking support ...
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

White-spirit wrote:Thanks.
But what means "page aligned"
He means that all paging structures must be aligned on a page-boundary, i.e. for protected mode this means that they must be located on a multiple of 4kiB. Given the value of cr3 in your dump, your's obviously aren't...

Regards,
John.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Page alignment isn't too hard:

Code: Select all

#define PAGE_ALIGNED( p ) (p & ~0xFFF)
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Thanks but it still doesn't work ...
I've aligned the addresses to the previous page boundary, and now I'm getting this from Bochs :

Code: Select all

00078761354i[CPU0 ] CPU is in protected mode (active)
00078761354i[CPU0 ] CS.d_b = 32 bit
00078761354i[CPU0 ] SS.d_b = 32 bit
00078761354i[CPU0 ] EFER   = 0x00000000
00078761354i[CPU0 ] | RAX=0000000080000011  RBX=000000000002d000
00078761354i[CPU0 ] | RCX=0000000000109c7c  RDX=000000000000002e
00078761354i[CPU0 ] | RSP=00000000001072b0  RBP=00000000001072b0
00078761354i[CPU0 ] | RSI=0000000000053c8e  RDI=0000000000053c8f
00078761354i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00078761354i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00078761354i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00078761354i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00078761354i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00078761354i[CPU0 ] | SEG selector     base    limit G D
00078761354i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00078761354i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078761354i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00078761354i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00078761354i[CPU0 ] | RIP=00000000001014bc (00000000001014bc)
00078761354i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000040
00078761354i[CPU0 ] | CR3=0x40108c80 CR4=0x00000000
00078761354i[CPU0 ] >> add byte ptr ds:[eax], al : 0000
00078761354e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting
Here's the modified code :

Code: Select all

#define log2ph(x)  (((void*)(x))+0x40000000)
#define ph2log(x)  (((void*)(x))-0x40000000)
#define p_align(x) (((u32int)(x)) & (u32int)~0xFFF)

u32int page_dir[1024];
u32int page_table[1024][1024];
u32int* aligned_page_dir;
u32int* aligned_page_table;

void align_tables(){
	aligned_page_dir = (u32int*)(p_align(page_dir));
	aligned_page_table = (u32int*)(p_align(page_table));
}

void init_tables(){
	int i,j;
	int ph_address = 0;
	for( i = 0; i < 1024; i++ ){
		for( j = 0; j < 1024; j++){
			aligned_page_table[1024 * i + j] = ph_address;
			aligned_page_table[1024 * i + j] = aligned_page_table[1024 * i + j] | 3;
			ph_address += 4096;
		}
	aligned_page_dir[i] = &aligned_page_table[i];
	aligned_page_dir[i] |= 3;
	}
}

void load_pagedir(){
	asm volatile ("\
	movl %0, %%eax; \
	movl %%eax, %%cr3; \
	" :: "r" (log2ph(aligned_page_dir)));
}

void activate_paging(){
	asm volatile ("\
	movl %cr0, %eax; \
	or $0x80000000, %eax; \
	movl %eax, %cr0 \
	");
}

void init_paging(){
	printf("[DEBUG] activate_paging is located at virtual address 0x8:%h, and physical address %h", &activate_paging, log2ph(&activate_paging)); 
	align_tables();
	init_tables();
	printf("\n *Loading page directory...");
	load_pagedir();
	printf("[DONE]");
	printf("\n *Activating paging...");
	activate_paging();
	printf("[DONE]");
	printf("\n *Paging is...");
}
Any idea ? :?

Thanks :-)
Working on multi-tasking support ...
zerosum
Member
Member
Posts: 63
Joined: Wed Apr 09, 2008 6:57 pm

Post by zerosum »

00078761354i[CPU0 ] | CR3=0x40108c80 CR4=0x00000000
You need to page-align your structures, as suggested above. The value in CR3 shows that your top-level structure at least is not page-aligned. Either that or you're loading the wrong address into CR3.
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

zerosum wrote:
00078761354i[CPU0 ] | CR3=0x40108c80 CR4=0x00000000
You need to page-align your structures, as suggested above. The value in CR3 shows that your top-level structure at least is not page-aligned. Either that or you're loading the wrong address into CR3.
I agree with you that the value of CR3 is not page aligned, but the structures are already aligned, what am I doing wrong ?

Thanks
Working on multi-tasking support ...
zerosum
Member
Member
Posts: 63
Joined: Wed Apr 09, 2008 6:57 pm

Post by zerosum »

I've not really gone through your code to be honest, but I can see a problem on the first couple of lines...

You've declared your paging structures as simple arrays inside your kernel. Do you know where the compiler is putting these? I'd suggest their position is not page-aligned ;-)

What I've done is put my kernel paging structures at the first page boundary after the kernel ends. It doesn't matter where they are as long as they're page-aligned.

Simply taking the address of the arrays you've created and masking out bits doesn't make them page-aligned... it just gives the wrong address when you try to load it into CR3, compounding the problem.

So there looks to me to be two problems (possibly more, I stopped at this point):

1) The paging structures are still not page-aligned
2) You're loading the wrong value into CR3

Cheers,
Lee
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

Yeaaaaaah, it works fine just after deleting log2ph .
An explanation please? I thought CR3 needs the physical address :?

EDIT : It fails if I call the "sti" instruction :

Code: Select all

00078788024i[CPU0 ] CPU is in protected mode (active)
00078788024i[CPU0 ] CS.d_b = 32 bit
00078788024i[CPU0 ] SS.d_b = 32 bit
00078788024i[CPU0 ] EFER   = 0x00000000
00078788024i[CPU0 ] | RAX=0000000000000000  RBX=0000000000108c60
00078788024i[CPU0 ] | RCX=0000000000109c7c  RDX=0000000000000020
00078788024i[CPU0 ] | RSP=00000000001072d8  RBP=00000000001072f0
00078788024i[CPU0 ] | RSI=0000000000053c8e  RDI=0000000000053c8f
00078788024i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00078788024i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00078788024i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00078788024i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00078788024i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf ZF af PF cf
00078788024i[CPU0 ] | SEG selector     base    limit G D
00078788024i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00078788024i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00078788024i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00078788024i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00078788024i[CPU0 ] | RIP=0000000000100c13 (0000000000100c13)
00078788024i[CPU0 ] | CR0=0x80000011 CR1=0x0 CR2=0x0000000000000000
00078788024i[CPU0 ] | CR3=0x00508000 CR4=0x00000000
00078788024i[CPU0 ] >> call .+0x00000477 (0x0010108f) : E877040000
00078788024e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Last edited by White-spirit on Thu May 01, 2008 6:18 am, edited 1 time in total.
Working on multi-tasking support ...
zerosum
Member
Member
Posts: 63
Joined: Wed Apr 09, 2008 6:57 pm

Post by zerosum »

It does.

And how the hell that is working, I have no idea :)

Cheers,
Lee
White-spirit
Member
Member
Posts: 89
Joined: Sun Mar 23, 2008 2:23 pm
Location: [0x8:0x1000]

Post by White-spirit »

The interrupts don't work, it's normal ?
I'm setting the IDT before activating paging .
Working on multi-tasking support ...
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

An explanation please? I thought CR3 needs the physical address
Exactly! Why were you adding 0x40000000 to get a "physical" address? Do you even understand what you're talking about here?
Post Reply