1
Lowlevel-Coding / Paging Fehler: Bit 31 in cr0
« am: 22. June 2008, 21:44 »
Hallo nachdem mir hier schon so schnell mit meiner memalloc Funktion geholfen wurde, habe ich wieder ein Problem an dem ich schon einige Zeit sitze.
Situation:
Ich lege erst ein PageDirectory und 2 PageTables an. Die erste Table mappt die ersten 4 MB Virtuellen Speicher auch in die ersten 4 MB der Physischen Speichers, und die 2te Mappt den Speicherbereich bei genau 3GB an 0xB8000 wo sich ja der Video speicher befindet.
Anschließend setze ich das Bit 31 in cr0 um Paging zu aktivieren.
Wenn ich jetz ganz normal auf die Adresse 0xB8000 zugreife geht alles gut nur wenn ich auf 0xC0000000 (3GB) zugreife bekomme ich eine Exception.
Problem:
Obwohl ich Bit 31 gesetzt habe ist es nicht gesetzt wenn mein Interrupt Handler aufgerufen wird. Ich denke das er mir das Bit garnicht richtig setzt.
Frage:
Ist mein Code falsch (Code folgt unten) oder gibt es Fälle wo er das Bit einfach nicht setzten kann / bzw löscht der Prozessor das Bit 31 bei einer Exception automatisch ?
Wer net wenn mir da jemand Auskunft geben könnt.
Code:
Definition
Assembler Code
C Code
Initialisierung und Test:
Situation:
Ich lege erst ein PageDirectory und 2 PageTables an. Die erste Table mappt die ersten 4 MB Virtuellen Speicher auch in die ersten 4 MB der Physischen Speichers, und die 2te Mappt den Speicherbereich bei genau 3GB an 0xB8000 wo sich ja der Video speicher befindet.
Anschließend setze ich das Bit 31 in cr0 um Paging zu aktivieren.
Wenn ich jetz ganz normal auf die Adresse 0xB8000 zugreife geht alles gut nur wenn ich auf 0xC0000000 (3GB) zugreife bekomme ich eine Exception.
Problem:
Obwohl ich Bit 31 gesetzt habe ist es nicht gesetzt wenn mein Interrupt Handler aufgerufen wird. Ich denke das er mir das Bit garnicht richtig setzt.
Frage:
Ist mein Code falsch (Code folgt unten) oder gibt es Fälle wo er das Bit einfach nicht setzten kann / bzw löscht der Prozessor das Bit 31 bei einer Exception automatisch ?
Wer net wenn mir da jemand Auskunft geben könnt.
Code:
Definition
Code: [Auswählen]
struct Paging_PageDirectory
{
unsigned int PageTableAdress[1024];
};
struct Paging_PageTable
{
unsigned int PhysPageAdress[1024];
};
/*
Aktiviert Paging.
*/
void Paging_Enable( void );
/*
Deaktiviert Paging.
*/
void Paging_Disable( void );
/*
Ändert das aktive PageDirectory und
gibt die Adresse des Alten zurück
*/
void Paging_SwapDirectory( struct Paging_PageDirectory* Directory);
/*
Gibt das aktive PageDirectory zurück.
*/
struct Paging_PageDirectory* Paging_GetActivDirectoy( void );
/*
Erstellt ein PageDirectory an übergeben Adresse.
*/
struct Paging_PageDirectory* Paging_CreatePageDirectory( void* Adress);
/*
Fügt einen Eintrag im Angebeben PageDirectory hinzu und
erstellt eine PageTable an angebener Adresse.
*/
struct Paging_PageTable* Paging_AddPageDirectoryEntry(unsigned short Entry,void* PageTableAdress,struct Paging_PageDirectory* PagingDirectory);
/*
Gibt einen Eintrag aus einem PageDirectory zurück.
*/
struct Paging_PageTable* Paging_GetPageTable(struct Paging_PageDirectory* Directory,unsigned short Entry);
/*
Fügt einen Eintrag in eine PageTable hinzu.
*/
void Paging_AddPageTableEntry(struct Paging_PageDirectory* Directory,unsigned short DirectoryEntry,unsigned short TableEntry,void* PhysAdress);
Assembler Code
Code: [Auswählen]
;C: void Paging_Enable( void );
_Paging_Enable:
push eax
mov eax,cr0 ;cr0 in eax laden
or eax,0x80000000 ;Bit Nr. 31 setzen
mov cr0,eax ;eax in cr0 schreiben
pop eax
ret ;zurück
;C: void Paging_Disable( void );
_Paging_Disable:
push eax
mov eax,cr0 ;cr0 in eax laden
xor eax,10000000000000000000000000000000b ;Bit Nr. 31 löschen
mov cr0,eax ;eax in cr0 schreiben
pop eax
ret
;C: void Paging_SwapDirectory( unsigned int DirectoryAdress );
_Paging_SwapDirectory: ; 1 Parameter: Adresse des neuen PageDirectory
push ebp
mov ebp, esp
push eax
mov eax, [ebp+8] ;Adresse nach eax lesen
mov cr3, eax
pop eax
mov esp, ebp
pop ebp
ret
;C: unsigned int Paging_GetActivDirectoy( void );
_Paging_GetActivDirectory:
mov eax,cr3 ;cr3 in eax laden
ret ;zurück (eax = Adresse)
C Code
Code: [Auswählen]
/*
Erstellt ein PageDirectory an übergeben Adresse.
*/
struct Paging_PageDirectory* Paging_CreatePageDirectory( void* Adress)
{
//Überprüfen ob gültige Adress
if((((unsigned int)Adress)&0xFFFFF000)!=((unsigned int)Adress))
{
KMSG("Invalid Page DIrectory Adress\n\r");
//1 Sekunde warten
timer_waitticks(100);
}
//
memset(Adress,0x00,4096);
return (struct Paging_PageDirectory*)Adress;
};
/*
Fügt einen Eintrag im Angebeben PageDirectory hinzu und
erstellt eine PageTable an angebener Adresse.
*/
struct Paging_PageTable* Paging_AddPageDirectoryEntry(unsigned short Entry,void* PageTableAdress,struct Paging_PageDirectory* PagingDirectory)
{
//In Directory Eintragen
PagingDirectory->PageTableAdress[Entry] = (((unsigned int)PageTableAdress) | 0x007);
//Paging Table mit 0 füllen
memset(PageTableAdress,0x00,4096);
//PageTable zurückgeben
return (struct Paging_PageTable*)PageTableAdress;
};
/*
Gibt einen Eintrag aus einem PageDirectory zurück.
*/
struct Paging_PageTable* Paging_GetPageTable(struct Paging_PageDirectory* Directory,unsigned short Entry)
{
return (struct Paging_PageTable*)((Directory->PageTableAdress[Entry]) ^ 0x007);
};
/*
Fügt einen Eintrag in eine PageTable hinzu.
*/
void Paging_AddPageTableEntry(struct Paging_PageDirectory* Directory,unsigned short DirectoryEntry,unsigned short TableEntry,void* PhysAdress)
{
struct Paging_PageTable* Table = Paging_GetPageTable(Directory,DirectoryEntry);
Table->PhysPageAdress[TableEntry] = (((unsigned int)PhysAdress) | 0x007);
};
Initialisierung und Test:
Code: [Auswählen]
struct Paging_PageDirectory* Directory = Paging_CreatePageDirectory(highmem_alloc());
Paging_AddPageDirectoryEntry(0,highmem_alloc(),Directory);
Paging_AddPageDirectoryEntry(768,highmem_alloc(),Directory);
//die Ersten 4 MB
int i=0;
unsigned int Phys = 0x00000000;
for(;i<1024;i++)
{
Paging_AddPageTableEntry(Directory,0,i,(void*)Phys);
Phys += 0x1000;
};
//3GB Erste Page
Paging_AddPageTableEntry(Directory,768,0,(void*)0xB8000);
Paging_SwapDirectory(Directory);
Paging_Enable();
KMSG("Paging Enabled!");
timer_waitticks(200);
char* Mem = 0xC0000000; //3 GB
char* String = "Test... Dies ist an die 3 GB Grenze geschrieben!";
for(i=0;i<strlen(String);i++)
{
*Mem = *String;
Mem++;
*Mem = KVC_White;
Mem++;
}