paging problem

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.
Post Reply
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

paging problem

Post by bsunisol »

hi,
i have a problem with my paging setup.
i used this tutorial, too.

but when i call the paging_install() funktion, bochs crashes.
00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00016344393-i-@0000071a-[CPU0 ] protected mode
00016344393-i-@0000071a-[CPU0 ] CS.d_b = 32 bit
00016344393-i-@0000071a-[CPU0 ] SS.d_b = 32 bit
00016344393-i-@0000071a-[CPU0 ] | EAX=80000011 EBX=00000400 ECX=00000000 EDX=00000000
00016344393-i-@0000071a-[CPU0 ] | ESP=000104c7 EBP=000104c7 ESI=003f6000 EDI=00000010
00016344393-i-@0000071a-[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00016344393-i-@0000071a-[CPU0 ] | SEG selector base limit G D
00016344393-i-@0000071a-[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00016344393-i-@0000071a-[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00016344393-i-@0000071a-[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00016344393-i-@0000071a-[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00016344393-i-@0000071a-[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 000fffff 1 1
00016344393-i-@0000071a-[CPU0 ] | FS:0000( 0000| 0| 0) 000ffff0 0000ffff 0 0
00016344393-i-@0000071a-[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00016344393-i-@0000071a-[CPU0 ] | EIP=0000071a (0000071a)
00016344393-i-@0000071a-[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x80000011
00016344393-i-@0000071a-[CPU0 ] | CR3=0x00120000 CR4=0x00000000
00016344393-i-@0000071a-[CPU0 ] >> add byte ptr ds:[eax], al : 0000
00016344393-e-@0000071a-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
here is my code:

paging.h

Code: Select all

#ifndef __PAGING_H_
#define __PAGING_H_

/* ***************************************************************************** */

typedef struct _PageTableEntry {				/*  */
	unsigned int	present		: 1;			/*  */
	unsigned int	read_write	: 1;			/*  */
	unsigned int	level		: 1;			/*  */
	unsigned int	reserved_1	: 2;			/*  */
	unsigned int	accessed	: 1;			/*  */
	unsigned int	dirty		: 1;			/*  */
	unsigned int	reserved_2	: 2;			/*  */
	unsigned int	available	: 3;			/*  */
	unsigned int	address		:20;			/*  */
} PageTableEntry, *pPageTableEntry;

/* ***************************************************************************** */

#define PAGE_NOT_PRESENT		0x00
#define PAGE_READ				0x00
#define PAGE_LEVEL_SUPERVISOR	0x00
#define PAGE_PRESENT			0x01
#define PAGE_READ_AND_WRITE		0x01
#define PAGE_LEVEL_USER			0x01

/* ***************************************************************************** */

pPageTableEntry	PageDirectory;
pPageTableEntry	PageTable;

/* ***************************************************************************** */

void paging_install();
void CreatePageTableEntry( unsigned int num, unsigned long address, unsigned int level,
						   unsigned int read_write, unsigned int present, unsigned int available );
void CreatePageDirectoryEntry( unsigned int num, unsigned long address, unsigned int level,
							   unsigned int read_write, unsigned int present, unsigned int available );

/* ***************************************************************************** */

#endif
paging.c

Code: Select all

#include "paging.h"

/* ***************************************************************************** */

// pPageTableEntry	PageDirectory	= (pPageTableEntry) 0x00120000;
// pPageTableEntry	PageTable		= (pPageTableEntry) 0x00120100;

/* ***************************************************************************** */

void paging_install() {
	unsigned long tmp_address = 0;
	unsigned int i;

	PageDirectory	= (pPageTableEntry) 0x00120000;
	PageTable		= (pPageTableEntry) 0x00121000;

	// map the first 4MB of memory
	for( i; i < 1024; i++, tmp_address += 4096 ) {
		CreatePageTableEntry( i,
							  tmp_address,
							  PAGE_LEVEL_SUPERVISOR,
							  PAGE_READ_AND_WRITE,
							  PAGE_PRESENT,
							  0 );
	}

	CreatePageDirectoryEntry( 0,
							  (unsigned long) PageTable,
							  PAGE_LEVEL_SUPERVISOR,
							  PAGE_READ_AND_WRITE,
							  PAGE_PRESENT,
							  0 );

	for( i=1; i < 1024; i++ ) {
		CreatePageDirectoryEntry( i,
								  0,
								  PAGE_LEVEL_SUPERVISOR,
								  PAGE_READ_AND_WRITE,
								  PAGE_NOT_PRESENT,
								  0 );
	};

	write_cr3( (unsigned long) PageDirectory );
	write_cr0( read_cr0() | 0x80000000 );
}

/* ***************************************************************************** */

void CreatePageTableEntry( unsigned int num,
						   unsigned long address,
						   unsigned int level,
						   unsigned int read_write,
						   unsigned int present,
						   unsigned int available ) {
	PageTable[num].address		= (address		& 0x0FFFFF);
	PageTable[num].level		= (level		& 0x000001);
	PageTable[num].read_write	= (read_write	& 0x000001);
	PageTable[num].present		= (present		& 0x000001);
	PageTable[num].available	= (available	& 0x000007);
}

/* ***************************************************************************** */

void CreatePageDirectoryEntry( unsigned int num,
							   unsigned long address,
							   unsigned int level,
							   unsigned int read_write,
							   unsigned int present,
							   unsigned int available ) {
	PageDirectory[num].address		= (address		& 0x0FFFFF);
	PageDirectory[num].level		= (level		& 0x000001);
	PageDirectory[num].read_write	= (read_write	& 0x000001);
	PageDirectory[num].present		= (present		& 0x000001);
	PageDirectory[num].available	= (available	& 0x000007);
}

/* ***************************************************************************** */
its just a little modified for better bitfieldhandling.
but wheres my error?
could the pagedirectory or pagetable address
be unvalid?

thanks
Uni_Sol
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: paging problem

Post by jnc100 »

Seems like you're triple faulting on a GP fault when you're trying to access an interrupt. Is your idt set up? Its most likely that the initial exception is a page fault (as this happens just after setting up paging). Your CR3 looks to be set up okay, but I haven't checked that the paging structures are okay.

One way to see if to look at the EIP of the error (here its 0x71a), enter the bochs debugger and type 'lbreak 0x71a' then 'c' to execute. It should break at this instruction. Then, type 'info tab' to see your page tables. I suspect, though, that the error is here:
bsunisol wrote: // map the first 4MB of memory
for( i; i < 1024; i++, tmp_address += 4096 ) {
You don't initialise 'i'. Its whatever value is on the stack at the location where gcc allocates it. Try for(i = 0; i < 1024 ...

Regards,
John.
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post by bsunisol »

ok now i is 0 but it still doesnt work.

but the opcode for the instruction at 71a is "00 00" bochs says.
but in the listing its "31 c0"

info tab:
0x00XXX000-0x00XXXFFF -> 0xFFFFF000-0xFFFFFFFF
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

I think it has something to do with these lines of code:

Code: Select all

...
PageTable[num].address = (address & 0x0FFFFF); 
...
PageDirectory[num].address = (address & 0x0FFFFF);
...
you take the bottom 20 bits of the address while you should take the top 20 bits instead...
Seems like you're triple faulting on a GP fault
No, its a pagefault. CR2 is set to the address involved in the executed instruction (eax)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post by bsunisol »

ok corrected that.
but still the same.....

my bochs debug shows that its executing some
order i never coded at this position.
the first is the wrong one and the second is the
right instruction one......
what does that mean?
Attachments
bochs screenshot
bochs screenshot
Unbenannt-1 Kopie.gif (28.56 KiB) Viewed 2447 times
INF1n1t
Member
Member
Posts: 60
Joined: Fri Dec 22, 2006 5:32 pm
Location: Somewhere Down...

Post by INF1n1t »

Let me see your CR* write and read functions,....please?
I think, I have problems with Bochs. The biggest one: Bochs hates me!
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post by bsunisol »

yes of course!!

Code: Select all

; ***********************************************
; unsigned int read_cro()
_read_cr0:
	mov	eax, cr0
	retn

; ***********************************************
; void write_cr0()
_write_cr0:
	push	ebp
	mov	ebp, esp
	mov	eax, [ebp+8]
	mov	cr0,  eax
	;xor	eax, eax
	pop	ebp
	retn

; ***********************************************
; unsigned int read_cr3()
_read_cr3:
	mov	eax, cr3
	retn

; ***********************************************
; void write_cr3()
_write_cr3:
	push	ebp
	mov	ebp, esp
	mov	eax, [ebp+8]
	mov	cr3, eax
	;xor	eax, eax
	pop	ebp
	retn
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

you can't debug past a triple-fault. Its bound to do weird things.
Let me see your CR* write and read functions,....please?
Also, a floppy image and the new version of the code would be helpful in diagnosing the problem. But as you know bochs' debugger i doubt i can find anything you can not. Try using the x and xp commands to check the exact contents of the paging structures.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

Combuster wrote:
Seems like you're triple faulting on a GP fault
No, its a pagefault. CR2 is set to the address involved in the executed instruction (eax)
What I meant to say before was that yes, the initial exception was probably a page fault, but then:
bsunisol wrote: 00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
...
00016344393-e-@0000071a-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
suggests that the idt is not set up properly, or more likely that it was and then something went wrong with the paging that caused the idt to become unavailable.

@bsunisol: You could try locating the fault in your code by inserting a line like while(1); after the lines in paging_install() and then removing them one at a time to see where the fault starts occurring.

EDIT: just logged in to post and then noticed your bochs debug output. I see you're debugging the right part. Can you please post the output of 'info tab' immediately after the mov cr0, eax command?

Regards,
John.
INF1n1t
Member
Member
Posts: 60
Joined: Fri Dec 22, 2006 5:32 pm
Location: Somewhere Down...

Post by INF1n1t »

bsunisol wrote:yes of course!!
; ***********************************************
; void write_cr0()
_write_cr0:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr0, eax
;xor eax, eax
pop ebp
retn[/code]
Oh, I just saw the comment. So how is it possible ; xor eax, eax to be compiled as xor ax,ax (the comments should be skipped)...
Also, a suggestion -> in this function you should PUSH EAX and then POP it, because you don't know, what was in it (what gcc put there). You should also mov eax, [ebp+C], if you PUSH EAX.

Also:

Code: Select all


00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00016344393-e-@0000071a-[CPU0 ] interrupt(): gate descriptor is not valid sys seg 
Have you not solved the problem, already? I think you should have!
Last edited by INF1n1t on Mon Apr 30, 2007 9:53 am, edited 1 time in total.
I think, I have problems with Bochs. The biggest one: Bochs hates me!
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post by bsunisol »

hi,
the xor ax, ax command is from the bios.
the last instruction from code is marked red
on the screenshot.
he moves ax back to cr0 just as ordered and
then executes an 00 00 opcode. but i havent
written such code. and then he does the right
opcode, but the fault happened in the wrong
instruction. (marked red)

thats all in the write_cr0 function. all addresses
are right. there is no currupt jmp or call.
0x00711 is the valid address of that function.

i dont know whats the matter that he takes a
wrong opcode.

now i have no inet for a week. i will look up here
again next weekend.

tanks.
Uni_Sol
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Also, the idea behind inserting a while(1); does not apply here. We know what happens. PG is set and consequently all of memory is messed up because of it. The crash always happens after mov cr0, eax (0x80000011).

The one thing i'd do is to check the values of cr3, and everything it points to:

Code: Select all

bochs> dump_cpu
...
CR3=0xsomething
....
bochs> x /10 0xsomething
... 0xsomethingelse ...
...
bochs> x /10 0xsomethingelse
but we'll see in a week...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

Okay, I think there's some confusion as to what's going on here. This is my interpretation:

- Your code sets up some page tables and a page directory.

- You correctly load EAX with the location of your page directory

- You then (correctly) transfer this address from EAX to CR3

- You then load EAX with the old value of CR3 OR'd with 0x80000000

- Paging is enabled by moving this value to CR3

Then things start to go wrong.

If you read your bochs debug, you will notice that the next instruction is executing from 0xfffff71a, not, as you would expect, 0x0000071a.
The reason for this is not because you jumped there, because EIP is still correct at 0x0000071a. You are mapping the virtual address 0x0000071a to the physical address 0xfffff71a. ie there is something wrong with the mapping of the first page of the first page table.

Now, your emulator doesn't have physical memory at 0xfffff71a. It therefore, when asked for the next instruction to execute, returns 0000, which just happens to be the opcode for 'add byte ptr ds:[eax], al', so the emulated CPU happily tries to execute it.

EAX is still loaded with CR3 OR 0x80000000. Eek. DS is 0x10. Therefore, you are trying to load the value of AL into virtual address 0x10:0x80000011, which maps to logical address 0x80000011 as you are using flat segmenting.

This page is marked as not present, therefore you generate a page fault, and set CR2 (the missing address) to 0x80000011.

The CPU then looks for the interrupt vector for the page fault. Unfortunately, whichever bad setup in the page tables that caused the first problem, also means that the idt is also badly mapped.

It reads garbage or, in bochs speak:
Bochs wrote:interrupt(): gate descriptor is not valid sys seg
Which is a GP fault. So it looks for the GP handler, and yet again:
Bochs wrote:interrupt(): gate descriptor is not valid sys seg
which is your triple fault.

I hope this explains everything.

So the error is with your paging setup.

So I ask once again, please (when you're back), post the output of the bochs debugger command 'info tab' immediately after the instruction to load cr0.

Regards,
John.
INF1n1t
Member
Member
Posts: 60
Joined: Fri Dec 22, 2006 5:32 pm
Location: Somewhere Down...

Post by INF1n1t »

Well, I looked at the code he gave: I ask where he mapped 0x8000000 (virtual) to anything physical? He maps, the first 4 MB identically (physical == virtual) from the code I saw. May be I missed something important in the code, but: he should find the 512th page directory entry (for the last 2 GBs in the virtual memory) and then fill it with information. What he does, is to fill the first page directory entry, which is covering the first 4 MB virtual addresses, not the :

2GB to 2GB+4MB
I think, I have problems with Bochs. The biggest one: Bochs hates me!
User avatar
bsunisol
Member
Member
Posts: 40
Joined: Fri Apr 06, 2007 3:00 pm
Location: Germany, Berlin and near Hamburg

Post by bsunisol »

thanks for the answeres.

but my laptop is broken. :( :( :(
so i can't work for a time.
i'll post here again when i know more.
sry

and thanks for your help.

Uni_Sol
Post Reply