Page 1 of 2
PAGING
Posted: Thu Oct 20, 2005 8:24 am
by zack
Hello all
i've a problem with my paging code. the emulator / pc reboots again and again..
could you find a bug in my code?
Code: Select all
/*
;
;[1] Informations
;
; Last Modified: 21. Oktober 2004
; Begin: 15. Juni 2004
; Version: 0.000
; Coder: z4ck
;
;
;[2] Tasks
;
; Task Done Coder
;----------------------------------------------------------------
; - [ 0%] z4ck
;----------------------------------------------------------------
; TOTAL [ 0%] z4ck
;================================================================
*/
#include <memory.h>
#include <io.h>
/***************************************/
//Global Variables
PageDir *PageDirectory;
PageTbl *PageTable;
void SetupPaging()
{
PageDirectory = (PageDir *) 0x100000;
PageTable = (PageTbl *) 0x101000;
unsigned long i = 0;
for (; i < 1024; i++)
{
PageDirectory[i].PageTable = (PageTbl *)((unsigned long)&PageTable[i] | PAGE_RW | PAGE_PRE);
}
MapMemory( 0, 0, 0x100, PAGE_RW | PAGE_PRE);
MapMemory( 0x10000, 0x10000, 10, PAGE_RW | PAGE_PRE);
MapMemory( 0x100000, 0x100000, 1, PAGE_RW | PAGE_PRE);
MapMemory( 0x101000, 0x101000, 1, PAGE_RW | PAGE_PRE);
WriteCr( (unsigned long)PageDirectory, 3);
WriteCr( (ReadCr(0) | 0x80000000) , 0);
};
int SetPage ( unsigned long _phyAdress, unsigned long _vAdress, unsigned long _opt)
{
unsigned long table = _vAdress >> 22;
unsigned long entry = ( (_vAdress & 0xFFFFF000) << 10) >> 22;
if (table < 1024 && entry < 1024)
{
PageDirectory[table].PageTable->PageFrame[entry] = _phyAdress | _opt;
return 1;
}
return 0;
};
int MapMemory ( unsigned long _phyAdress, unsigned long _vAdress, unsigned long _lenght, unsigned long _opt)
{
while (_lenght > 0)
{
SetPage (_phyAdress, _vAdress, _opt);
_vAdress += 4096;
_phyAdress += 4096;
_lenght--;
}
return 0;
};
void *malloc(unsigned long _size)
{
return (void *) 0;
};
void free()
{
};
void memcpy(unsigned *_dest, unsigned *_src, unsigned long _lenght)
{
unsigned long i = 0;
for (; i < _lenght; i++)
_dest[i] = _src[i];
};
Re:PAGIN
Posted: Thu Oct 20, 2005 9:10 am
by Crazed123
Where are you loading your kernel? It looks like you may be pointing your page directory and tables at kernel code, overwriting said code and thus causing a triplefault.
Re:PAGIN
Posted: Thu Oct 20, 2005 9:15 am
by zack
this is my memory map...
i think it need a page which is not mapped and execute exception 14 page fault. but if so it shouldn't crash. in this rutine is a while(1);. and the video memory is also to hight: 0xE0000000. so it musst something wrong whit the paging code..
thx
Code: Select all
;[4] RAM
;
; 0x0000 - 0x03FF = Real-mode interrupt vector table (IVT)
; 0x0400 - 0x04FF = BIOS data area (BDA)
; 0x7C00 - 0x7DFF = Bootsector (512 bytes)
; 0x7E00 - 0x99FF = Root-Dir (14 * 512 bytes)
; 0x9A00 - 0xABFF = Fat-Table (9 * 512 bytes)
; 0xAC00 - 0xAE00 = Stack (512 bytes)
; 0x10000 - 0x9FFFF = Kernel (??? bytes)
; 0xA0000 - 0xBFFFF = VGA framebuffers
; 0xC0000 - 0xC7FFF = video BIOS (32K is typical size)
; 0xF0000 - 0xFFFFF = Motherboard BIOS (64K is typical size)
; 0x100000 - 0x101000 = Page Dir
; 0x101000 - 0x501000 = Page Table
Re:PAGING
Posted: Thu Oct 20, 2005 9:29 am
by bluecode
zack wrote:
Code: Select all
PageDirectory[table].PageTable->PageFrame[entry] = _phyAdress | _opt;
wrong
Code: Select all
unsigned int *pdir = (PageDirectory[table] & 0xFFFFF000);
pdir[entry] = _phyAdress | _opt;
Re:PAGING
Posted: Fri Oct 21, 2005 11:35 am
by zack
thx bluecode!
however this code snippet doesent work correctly..
allredy by the compilation appears errors:
-> ivalide bytecode by '&'
whats wrong whit my code and whats the differents between your.
can you explain me...
thx & greez
zack
Re:PAGING
Posted: Fri Oct 21, 2005 12:24 pm
by bluecode
hi,
your trying to get the address of the page table from the page directory, but only the 22 higher bits of the page directory entry are the actual address of the page table, the other 10 bits are reserved/used for flags, such as User/Supervisor Bit R/W bit, etc.
What yo get when you read the page-directory entry is sth. like this: 0x100003 (when the read page table address is 0x100000) so you've to clear the lower 10bits via the bitwise and operation.
perhaps you've to add a cast, but I'm not sure, because I don't know what type PageDirectory is of.
Code: Select all
unsigned int *pdir = (unsinged int *)((unsigned int)PageDirectory[table] & 0xFFFFF000);
pdir[entry] = _phyAdress | _opt;
[edit: You should post your definition of PageDir and PageTbl]
[edir2: btw. why are you setting all entries in the page directory to the same page table?]
Re:PAGING
Posted: Fri Oct 21, 2005 2:04 pm
by zack
1. here are the definitions:
typedef struct
{
unsigned int PageFrame[1024];
} __attribute__ ((packed)) PageTbl;
typedef struct
{
PageTbl *PageTable;
} __attribute__ ((packed)) PageDir;
2. i don't set them to the same pagetable. or?!
greez & thx
Re:PAGING
Posted: Fri Oct 21, 2005 2:41 pm
by zloba
Are you aware that your "memcpy" function works in 32-bit words, not bytes like standard one?
Which means that if you give it sizeof(something), it will copy 4 times more, possibly overwriting stuff..
I don't see if/where you use it and whether that could be a problem..
Re:PAGING
Posted: Fri Oct 21, 2005 3:28 pm
by bluecode
hi,
2. You do: In SetupPaging() you (want to
) loop through the 1024 entries of the page directory aren't you?
But you've got something else wrong . I'll show you how to do it right: The code that was where now are /*...*/ is correct.
zack wrote:
Code: Select all
void SetupPaging()
{
/*...*/
for (; i < 1024; i++)
{
/* ERROR1: You want to set the i-th entry of the Page table, so why are you looking for the i-th page directory ?
ERROR2: PageTable is a pointer to the page table why are you trying to get a pointer to an entry of the page table */
/*CORRECT:*/
PageDirectory->PageTable[i] = (PageTbl *)((unsigned long)PageTable | PAGE_RW | PAGE_PRE);
}
/*...*/
};
int SetPage ( unsigned long _phyAdress, unsigned long _vAdress, unsigned long _opt)
{
/*...*/
if (table < 1024 && entry < 1024)
{
/*ERROR: Same thing like above */
/*CORRECT:*/
PageTbl *pageTable = PageDirectory->PageTable[table];
pageTable = (PageTbl*)((unsigned long)pageTable & 0xFFFFF000);
pageTable->PageFrame[entry] = _phyAdress | _opt;
/*...*/
}
return 0;
};
Your memcopy doesn't work as described in the c standard. Did you know that? Your _length parameter MUST be the size of the memory region, but in 4Byte units.
Perhaps you didn't fully understand paging OR you're quite a beginner in C/C++, aren't you!?
Re:PAGING
Posted: Mon Oct 24, 2005 3:12 pm
by zack
if i do so like you wrote, i must change the struct to:
Code: Select all
typedef struct
{
PageTbl *PageTable[1024];
} __attribute__ ((packed)) PageDir;
.
now it works. the emulator / pc don't reboot.
but now the page dirs points all to the same table:
->
Code: Select all
for (; i < 1024; i++)
{
PageDirectory->PageTable[i] = (PageTbl *)((uint32_t) PageTable | PAGE_RW | PAGE_PRE);
}
.why can't i do this.
Code: Select all
for (; i < 1024; i++)
{
PageDirectory->PageTable[i] = (PageTbl *)((uint32_t) &PageTable[i] | PAGE_RW | PAGE_PRE);
}
and set them to the adress of each elemt of the array?
is this a wrong syntax?
thx realy for help and sorry for my language (i'm from switzerland...
)
Re:PAGING
Posted: Mon Oct 24, 2005 3:33 pm
by bluecode
zack wrote:why can't i do this.
Code: Select all
for (; i < 1024; i++)
{
PageDirectory->PageTable[i] = (PageTbl *)((uint32_t) &PageTable[i] | PAGE_RW | PAGE_PRE);
}
and set them to the adress of each elemt of the array?
is this a wrong syntax?
First of all, It's not wrong C/C++ syntax. You didn't understand paging completly. EVERY entry in the page directory points to it's OWN page table (not just one entry in a page table). Perhaps you should read the intel manual again (and again
) and look how the address translation from virtual to linear addresses is done:
cr3 -> pageDirectory (physical address)
virtual address looks like this:
|---------------22----------------12-------
| page dir entry | page table entry | offset |
--------------------------------------------
The address translatio from virtual to linear is done as followed:
First the cpu looks up the address of the page directory in cr3 (physical address). Then it takes the 10 highest bits of the virtual address as an index into the page directory. In the page directory there is just the physical address of a page table (and some flags). The cpu takes the bits from 12 to 22 from the virtual address as an index into the page table. In this page table there is the real physical address of the page frame.
The linear address is then this address from the page table + the bits from 0 to 12 from the virtual address.
Time to go to bed. good night.
btw. I'm from Germany and some people are from belgium,austria so english as native laguage is uncomon.
Re:PAGING
Posted: Mon Oct 24, 2005 3:46 pm
by zack
yes, i know this all.
but i have a array of pagetables. each one has 1024 entrys. and with &PageTable[0] i want the adress of the first PageTable. and so one... -> not the first entry of a pagetable, you know...
you don't understand what i want to say...
Re:PAGING
Posted: Fri Oct 28, 2005 2:46 am
by zack
so, i rewrote a part of my paging code. but it don't works yet.
whats wrong now??
Code: Select all
#define PAGE_PRE 0x01
#define PAGE_RW 0x02
/***************************************/
//Global Variables
uint32_t *PageDirectory;
uint32_t *PageTable;
/*************************************************************************
*************************************************/
/*************************************************************************
*************************************************/
/*************************************************************************
*************************************************/
/*************************************************************************
*************************************************/
void SetupPaging()
{
???
???
???PageDirectory ???= (uint32_t *) 0x100000;
???PageTable ??????= (uint32_t *) 0x101000;
???uint32_t i = 0;
???uint32_t j = 0;
???
???for (; i < 6; i++)
???{
??????PageDirectory[i] ???= ???(uint32_t)(PageTable + (4096 * i));
??????PageDirectory[i] ???= ???PageDirectory[i] | PAGE_RW | PAGE_PRE;
??????uint32_t *tabl = (uint32_t *)(PageDirectory[i] & 0xFFFFF000);
??????for (j=0;j < 1024; j++)
??????{
?????????
?????????tabl[j] = (uint32_t)(4096 * j * i);
?????????tabl[j] = tabl[j] | PAGE_RW | PAGE_PRE;
??????
??????}
???}
???WriteCr( (uint32_t)PageDirectory, 3);
???WriteCr( (ReadCr(0) | 0x80000000) , 0);
};
must i something look for specaly? could be the gdt wrong or i don't know what i made wrong...
thanks for help!!
Re:PAGING
Posted: Wed Nov 02, 2005 9:38 am
by zack
paging works now.
if i map the hole 4 gb linear allthing went right.
but if i only map this things i need, the the pc / emulator reboots.
what are important things to map?
now i map:
0 - 0xFFFFF -> bios stuff and kernel (0x10000 (+-16kb))
PageDirectory - 0x100000 0x100FFF
PageTables - 0x101000 - 0x500FFF
and the video memory 0xE000000 - E0240000 (1024*768*24bit)
what must i map too?
thanks
Re:PAGING
Posted: Thu Nov 03, 2005 1:17 am
by distantvoices
Ha ... You're most prolly missing to map something.
If I were you, I'd activate paging in the earliest of startup stubs of your kernel. Create temporary mappings. 1:1, from 0xc0000000 (or what so ever) to your needed size ...
link your kernel to the desired virtual address. Patch addresses in the early startup code ere paging is active.
Oh, and avoid telling ppl that they didn't understand what you mean. It's plain offending. Try to say it an other way around. You aren't a wordless lump of stone after all, are you?
These are my hints.
Btw: take a breath and lean back. then place printf's and stop-go code in your paging and startup stuff to trace it. You might find out where it bails out. Bochs tells btw. It delivers a cpu register excerpt alongside with kinda reason for the triple fault.