Autor Thema: [Gelöst] PageFault!  (Gelesen 12374 mal)

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« am: 24. January 2010, 11:15 »
Hi Community!

Taljeth hat in dem Thread Thema: C-Programm laden vollkommen recht gehabt! Irgendetwas stimmt mit meinem Paging noch immer nicht und ich komm einfach nicht dahinter WAS!

Folgende Routine initialisiert mein Paging:
/*die struktur kernelPagingStructure*/
struct kernelPagingStructure {
unsigned int *pageDirectory;
unsigned int *pageTable[1024];
unsigned short aktPageDirectory;
unsigned short aktPageTable;
};

//globaleVariable
struct kernelPagingStructure kernelPageMap;

void initPaging(){
unsigned int count;
        unsigned int ende = 0x400000;
kernelPageMap.pageDirectory = getFreeMemory();


for(count = 0; count < 1024; count++){
kernelPageMap.pageTable[count] = ((void *)0);
}

for(count = 0; count < ende;){
mapPage(count);
count += 0x1000;
}

   asm volatile( "mov %0, %%cr3" : : "r" (kernelPageMap.pageDirectory) );
   unsigned int cr0;
   asm volatile("mov %%cr0, %0": "=r"(cr0));
   cr0 |= 0x80000000;
   asm volatile("mov %0, %%cr0":: "r"(cr0));

pagingOn = 1;
}

diese Methode ruft void mapPage(unsigned int physMemory) auf:
#define MEMORY_PRESENT      0x1
#define PAGE_WRITEABLE      0x2
#define EVERYONE_ACCESSABLE 0x4
#define WRITE_THROUGH_ON 0x8
#define CACHING_OFF 0x10
void mapPage(unsigned int physMemory){
int pageFrames = physMemory / 0x1000;

int pageFrameIndex = pageFrames % 1024;
pageFrames /= 1024;
int pageTableIndex = pageFrames % 1024;
pageFrames /= 1024;
int pageDirIndex = pageFrames % 1024;

if(kernelPageMap.pageTable[pageTableIndex] == ((void *)0)){
kernelPageMap.pageTable[pageTableIndex] = getFreeMemory();
}

kernelPageMap.pageTable[pageTableIndex][pageFrameIndex] = physMemory | MEMORY_PRESENT | PAGE_WRITEABLE | EVERYONE_ACCESSABLE;
kernelPageMap.pageDirectory[pageTableIndex] = (unsigned int)kernelPageMap.pageTable[pageTableIndex] | MEMORY_PRESENT | PAGE_WRITEABLE | EVERYONE_ACCESSABLE;
}

Die Funktion void *getFreeMemory() liefert die Adressen 0x1000(physisch) 0x2000(physisch) und 0x3000(physisch) usw da diese physischen Adressen ja frei sind.

Das PageDirectory lässt sich auch ohne Anstände laden und auch der Kernel arbeitet ohne Probleme weiter, aber jetzt kommts!

Wenn ich mein Filesystem initialisieren will (FAT12), dann muss ich ja die FAT Tabelle auslesen. Das mache ich folgendermaßen:
//FAT ist eine globale Variable
unsigned short FAT[2880];

//die Funktion readFAT
void readFAT(){
int sektors = 0, aktEntry = 0, i,j = 0, first = 0;;
unsigned char b[4608];

printf("leseFat\n");
while(sektors < 9){
unsigned char *sek = readSectorLBA(sektors + 1);

for(i = 0; i < 512;i++){
b[j] = sek[i];
j++;
}
sektors++;
}

printf("alles gelesen\n");
j = 0;
while(aktEntry < 2880){
printf("zugriff FAT[%d]\n", aktEntry);
FAT[aktEntry] = up(b[j], b[j+1]);
aktEntry++;
j++;
printf("zugriff FAT[%d]\n", aktEntry);
FAT[aktEntry] = lo(b[j], b[j+1]);
aktEntry++;
j += 2;
}
}

Nun geht der Zugriff auf FAT 640 Mal gut und dann kommt die Page Fault Exception.



Nur warum? Ich Mappe doch die Adresse 0x119000. Ich Mappe jede Adresse bis 0x400000.

Ich hoffe ihr könnt mir in diesem Fall helfen, ich bin mit meiner Weisheit am Ende irgendetwas hab ich da übersehen!

Danke vielmals schonmal im Vorraus!
lg
« Letzte Änderung: 05. February 2010, 08:22 von gcalctool »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 24. January 2010, 11:25 »
int pageFrames = physMemory / 0x1000;

int pageFrameIndex = pageFrames % 1024;
pageFrames /= 1024;
int pageTableIndex = pageFrames % 1024;
pageFrames /= 1024;
int pageDirIndex = pageFrames % 1024;
Ich weiß zwar nicht genau, was du hier veranstaltest, aber vielleicht hilft es dir ja, wenn ich dir verrate, dass Paging auf i386 nur zweistufig ist.

Könnte es sein, dass das, was du pageTableIndex und pageDirIndex nennst, eigentlich dasselbe sein sollte?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 24. January 2010, 11:38 »
Ja stimmt hab ich vergessen zu löschen!
int pageDirIndex = pageFrames % 1024;verwende ich gar nicht!

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 24. January 2010, 12:04 »
Hm, ok. Ansonsten sehe ich im Moment in deinem Paging-Code nichts auffälliges. Vielleicht überschreibst du dir irgendeine Page Table beim Einlesen des Dateisystems versehentlich mit was anderem? Du kannst ja mal den Debugger deines Emulators hernehmen und dir anzeigen lassen, wie das PD und die entsprechende PT aussehen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 24. January 2010, 14:59 »
Danke taljeth für deine schnellen Antworten!

Ich habe deinen RAT befolgt und habe mir mit dem BOCHS Debugger mal den Speicher genauer angesehen.

Dabei habe ich herausgefunden, dass das Paging wunderbar funktioniert, wenn ich die Adressen von 0x0000 bis 0x2FFF auf reserviert setze.(Dh. ich kann mein PageDirectory erst auf 0x3000 setzen und die erste PageTable auf 0x4000) Ich habe keine Ahnung warum das so ist kann das mit GRUB zusammenhängen?

Außerdem hab ich noch eine Frage zu den bytes die mir BOCHS anzeigt:
zum Beispiel das PageDirectory an der stelle 0x3000:
Zitat von: grub
Addr   |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
-------+-------------------------------------------------
0x3000 | 27 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x3010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x3020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...

Was bedeutet da das Byte 0x27?

Danke!

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 24. January 2010, 15:13 »
Dabei habe ich herausgefunden, dass das Paging wunderbar funktioniert, wenn ich die Adressen von 0x0000 bis 0x2FFF auf reserviert setze.(Dh. ich kann mein PageDirectory erst auf 0x3000 setzen und die erste PageTable auf 0x4000) Ich habe keine Ahnung warum das so ist kann das mit GRUB zusammenhängen?
Nein, das liegt sicher nicht an GRUB. Der läuft nämlich schon lang nicht mehr, wenn dein Kernelcode ausgeführt wird. ;) Ich gehe davon aus, dass du dir den Speicher selber überschreibst und z.B. als Puffer beim Einlesen der Sektoren hernimmst oder so. Ist im Speicher nicht erkennbar, was es sein könnte, mit dem die Tabellen überschrieben werden?

Zitat
Was bedeutet da das Byte 0x27?
Das sind die unteren paar Bit von deinem Pagetableeintrag. 0x7 sind die Flags rw/user/present und 0x20 dürfte accessed oder sowas ähnliches sein, was von der CPU automatisch gesetzt wird.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 24. January 2010, 16:07 »
Hmm.
Ich hab eigentlich sonst nirgends direkten Zugriff auf die Adressen das lass ich zz noch alles den Compiler machen den den Floppy buffer lege ich zb so an:
static const char floppyMem[floppyBufLen] __attribute__((aligned(0x8000)));
die sonstigen speicherbereiche auch alle ueber arrays. NUR die PageTables und das PageDirectory lege ich durch direkten zugriff auf den Speicher an.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 24. January 2010, 16:20 »
Wo liegt denn dein Stack? Du packst da relativ große Arrays drauf, vielleicht läuft dir auch dein Stack über? Was du auch noch probieren könntest, wäre im Debugger einen Watchpoint auf eine Adresse zu legen, die überschrieben wird.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 24. January 2010, 17:07 »
hi taljeth!

Du hast recht es hat irgendetwas mit dem STACK zu tun!
Ich habe jetzt den Stack einmal ums doppelte größer gemacht und schon bekomme ich den Fehler wieder obwohl ich mein PageDir und meine PageTable verschoben habe! Das verstehe ich aber nicht ganz.

Mein Kernel wird an die Adresse 0x100000 geladen. Mein Stack ist 8192 Bytes groß(habs jetzt wieder zurückgeändert von 16384 auf 8192) und er wird an das Ende des Kernels kopiert:
.section multiboot

.align 4
.int 0x1badb002
.int 0x2
.int -0x1BADB004

.section .text

.extern kernel_init

.global _start
_start:
mov $kernelStack, %esp

push %ebx
call kernel_init

jmp .

.section bbs
.space 8192
kernelStack:

Wenn er nun zu groß werden würde, würde er doch den Kernel überschreiben (da der Stack ja nach unten wächst) und nicht Adressen die VOR(meine PageTable liegt auf 0x3000 und mein PageDirectory auf 0x4000) dem Kernel liegen. Stimmt das oder liege ich da falsch?

hier noch mein linkerfile:
ENTRY(_start)

SECTIONS
{
    . = 0x100000;

    .text : {
        *(multiboot)
        *(.text)
    }
    .data ALIGN(4096) : {
        *(.data)
    }
    .rodata ALIGN(4096) : {
        *(.rodata)
    }
    .bss ALIGN(4096) : {
        *(.bss)
    }
kernelEnd = .;
}

« Letzte Änderung: 24. January 2010, 17:15 von gcalctool »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 24. January 2010, 19:56 »
.section bbs
Das ist ein Tippfehler. Ich bin mir nicht sicher, wo er die Section dann hinpackt, wenn du sie im Linkerskript gar nicht erwähnst.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Programm Noob

  • Gast
Gespeichert
« Antwort #10 am: 25. January 2010, 00:02 »
Moin

Ich habe von gcalctool die sources bekommen, dort habe ich es eben probeweiser getestet mit bss anstelle bbs, der Fehler bleibt.

Programm Noob

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 25. January 2010, 11:44 »
hi ich habs hinbekommen ich weiß jetzt wo es gelegen ist!
DANKE für eure Hilfe!!!
@Programm Noob eine funktionierende Version ist Online und nun schreibe ich einen ELF Loader vl ICQst mich ja mal an: 252745823 :-)
« Letzte Änderung: 25. January 2010, 12:03 von gcalctool »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 25. January 2010, 14:34 »
hi ich habs hinbekommen ich weiß jetzt wo es gelegen ist!
Willst du es uns auch verraten? Es könnte dem nächsten helfen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 25. January 2010, 14:52 »
Willst du es uns auch verraten? Es könnte dem nächsten helfen.

Ok gerne!

Punkt 1: Der Stack war das Problem!
Jetzt musste ich mal herausfinden WAS genau mit dem Stack nicht stimmte. Jetzt habe ich mir mal die map datei vom Linker erstellen lassen und nachgesehen wo die Adresse des Stacks liegt:
                0x0000000000000000                PROVIDE (__start_bss, .)

bss             0x0000000000000000     0x5000
 bss            0x0000000000000000     0x5000 ./bin/boot.o
                0x0000000000005000                PROVIDE (__stop_bss, .)
Hier sehe ich also dass der Stack an der physischen Adresse 0x5000 Startet ich habe also 20480Byte platz für den Stack (Da dieser ja nach unten wächst). Angelegt wird der Stack ja in der boot.S mit folgendem Code:
.section bss
.space 20480
kernelStack:
bss geht also bei 0x0 an und dann mache ich einen Space von 20480Byte also 0x0000 bis 0x5000 jetzt setze ich im Kernel, im physischen MemoryManagement, die Adressen von 0x0 bis 0x5000 als RESERVIERT (dann kann ich da keinen Speicher mehr anfordern) und schon liegen meine PageTable und das PageDir AB 0x5000 und höher somit überschreibe ich mit dem Stack meine PageDir nicht und somit funktionierts.

Ich hoffe es stimmt so!

lg

Programm Noob

  • Gast
Gespeichert
« Antwort #14 am: 26. January 2010, 00:02 »
Schön das du´s geschafft hast.

@gcalctool hab mir dies mal von deiner Website geklaut :wink:

  0x0000 -   0x5000 -> STACK (wächst nach unten!)
  0x5000 - 0x100000 -> FREE (wird für die PageDirs und PageTables verwendet)
0x100000 - 0x400000 -> KERNEL
0x400000 - 0x900000 -> KERNEL HEAP
0x900000 -      ??? -> ???


Ich hätte da noch so 2 kleine Einwände erstens der Stack überschreibt die BIOS Data Area und zweitens wäre es vileicht aus Desingntechnischen Gründen besser den KERNEL HEAP vor den Kernel zu legen, also in etwa so:

0x0000 -   0x8000 -> BIOS Data Area
 0x8000 -   0x18000 -> STACK (wächst nach unten!)
 0x18000 - 0x108000 -> FREE (wird für die PageDirs und PageTables verwendet)
 0x108000 - 0x508000 -> KERNEL HEAP
 0x508000 - 0x908000 -> KERNEL
0x908000 -      ??? -> ???


Wenn nämlich jetzt der kernel größer wird, stören da nach keine weiteren sachen im Speicher, welche unter Umständen überschrieben werden könnten.

Programm Noob

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #15 am: 26. January 2010, 18:11 »
Zitat von: Programm Noob
zweitens wäre es vileicht aus Desingntechnischen Gründen besser den KERNEL HEAP vor den Kernel zu legen
Sicher?

Zitat von: Programm Noob
Wenn nämlich jetzt der kernel größer wird, stören da nach keine weiteren sachen im Speicher, welche unter Umständen überschrieben werden könnten.
Damit widersprichst du dir gerade selbst. :wink:

Der Kernel selbst (also der Code und die fest initialisierten Variablen, bss, etc.) wird nie größer. Das einzige, was größer werden kann, sind Heap und Stack. Deshalb sollte der Heap hinter den Kernel, damit er nach oben wachsen kann und nicht den Kernel überschreibt (So sehe ich das jedenfalls).

Programm Noob

  • Gast
Gespeichert
« Antwort #16 am: 26. January 2010, 20:22 »
Während der Entwicklung wächst doch der Kernel noch, weil es kommt mehr code und somit mehr Variablen rein, somit wird er größer und dann muss man nicht ständig die adresse der HEAP`s ändern

Vehrstehst du jetzt wie ich das meinte?

Programm Noob

gcalctool

  • Beiträge: 29
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 26. January 2010, 20:44 »

Ich hätte da noch so 2 kleine Einwände erstens der Stack überschreibt die BIOS Data Area


Ah Danke!
An das mit der Bios Data Area habe ich gar nicht gedacht!
Das werde ich berücksichtigen!!!

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #18 am: 26. January 2010, 21:00 »
Zitat von: Programm Noob
Während der Entwicklung wächst doch der Kernel noch, weil es kommt mehr code und somit mehr Variablen rein, somit wird er größer und dann muss man nicht ständig die adresse der HEAP`s ändern

Vehrstehst du jetzt wie ich das meinte?
Ja, aber dafür gibts doch Linkermagie. :wink:

Programm Noob

  • Gast
Gespeichert
« Antwort #19 am: 26. January 2010, 21:47 »
<Scherz> was is Linkermagie :? :? :? Muss ich das Verstehen :? :? :?</Scherz>
Einfacher ist es aber wenn man die linkermagie auser Acht lässt wenn man den Heap einfach unter dem Kernel Platziert.

Programm Noob

 

Einloggen