Autor Thema: Paging  (Gelesen 33237 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #60 am: 08. March 2009, 12:17 »
Das habe ich gemacht.
Also meine PD in die PD selbst eingetragen.
Nur wie muss ich dann damit weiter umgehen (mein Schema funktioniert ja leider nicht)?

Ich habe es bisher so gemacht, dass ich beim Erstellen einer Tabelle diese in die PD eingetragen.
Muss ich das in die PD eintragen, die in der PD steht?
Hoffentlich konnte ich mich halbwegs ausdrücken.
Der Satz verwirrt mich selbst ;).
Dann habe ich aber glaub ich ein Problem.
Wenn Paging aktiviert ist, trage ich ja virtuelle Adressen in die PD ein.
Das müssten aber physikalische sein, oder?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #61 am: 08. March 2009, 12:37 »
In PDs und PTs stehen immer physische Adressen, nie virtuelle.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #62 am: 08. March 2009, 13:08 »
Hmm....

Dann mache ich irgendwas anderes falsch.

Ich bschreibe mal die Initialisierung.

Ich reserviere mir eine PD die alle Teile für den Kernelspace mappt.
Dann schreibe ich den Kernel, die Bitmap, den VGA-Speicher und die PD selbst.
Alles wird 1:1 gemappt.
Dann aktiviere ich paging.
So weit funktioniert auch alles.

Wenn ich nun Pages allozieren möchte, schaue ich in der PD nach und suche eine freie Seite oder erstelle mir eine neue Tabelle.
Diese neue Tabellen wird natürlich auch in die PD eingetragen.
Wenn ich nun versuche auf eine allozierte Seite zuzugreifen, bekomme ich einen Pagefault.
Wieso?
An sich nehme ich diesen Hack ja auch vor.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #63 am: 08. March 2009, 14:20 »
Das kann ich so jetzt nicht sagen, wo der Fehler liegt. Deinen Code debuggen mußt du schon selbst. Am besten hältst du die qemu-VM mal an, nachdem du den PF bekommen hast. Dann schaust du nach, was cr2 ist, und versuchst diese Adresse im Monitor mit xp von Hand aufzulösen (auch auf die Flags achten). Vielleicht fällt dir dabei was auf.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #64 am: 08. March 2009, 16:17 »
Also ich habe halt mehrere PF.
Den einen kann ich beheben, indem ich jede Tabelle, die ich in die PD eintrage, auch noch in die PD als gemappt eintrage.
Also nicht einfach PD = PT sondern dann auch noch einmal die Adresse der PT in der PD eintrage.
Das macht an sich auch sinn, auch wenn ich denke, dass es ein wenig ineffektiv ist.
Wieso geht es nicht, dass ich die Tabelle einfach in der PD eintrage?

Der andere Pagefault taucht beim Zugriff auf einen angeblich gemappten Bereich auf. Den muss ich aber erst noch genauer debuggen
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #65 am: 08. March 2009, 16:37 »
Den einen kann ich beheben, indem ich jede Tabelle, die ich in die PD eintrage, auch noch in die PD als gemappt eintrage.
Also nicht einfach PD = PT sondern dann auch noch einmal die Adresse der PT in der PD eintrage.
Das macht an sich auch sinn, auch wenn ich denke, dass es ein wenig ineffektiv ist.
Versteh ich nicht. Gib mir mal einen Speicherdump, damit ich sehe, was du meinst. Oder gleich ein Floppy-Image, wo man das Problem sieht.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #66 am: 08. March 2009, 17:00 »
Naja, das sieht momentan so aus:
Ich habe meine PD mit 1024 Einträgen.
In jeden Eintrag kommt ja eine PT mit 1024 Einträgen.
Eine neue PT trage ich in die PD ein.
Wenn ich nun auf ein Element der PT zugreifen möchte um zu schauen, ob der Speicher frei ist, damit ich ihn belegen kann, bekomme ich den Pagefault.
Wenn ich aber die PT selbst mappe, dann kann ich darauf zugreifen.

table = (page_table_t)((uint32_t)krn_dir[i] & PAGING_REMOVEFLAGS);
for(k = 0; k < PAGING_TABLE_SIZE; k++){
//found a free page
if(table[k] == EMPTY && dir == -1){
dir = i;
tab = k;
}

Bei dem Zugriff table[k] bekomme ich einen Pagefault, wenn ich die table nicht selbst gemappt habe.

Ein image kann ich dir leider nicht geben, da ich das ganze schon wieder ein wenig überarbeitet habe.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #67 am: 08. March 2009, 17:06 »
Jo, das ist logisch. Aber das sollte eigentlich kein Problem darstellen, weil du ja sowieso alle PTs gemappt hast, wenn du das PD nochmal als PT wiederverwendest.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #68 am: 08. March 2009, 17:09 »
Das mache ich ja auch.
Ich mappe die PD selbst in der PD an der Stelle, an der sie auch physikalisch liegt.
Deshalb verstehe ich den Fehler ja auch nicht.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #69 am: 08. March 2009, 17:14 »
Du hast physisch Speicher für alle 1024 Page Tables reserviert? Mal abgesehen davon, daß die PTs natürlich nicht mehr physisch an derselben Stelle liegen können, sobald du mehrere Prozesse mit eigenem Speicherkontext hast.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #70 am: 08. March 2009, 17:20 »
Nein, ich alloziere Speicher nur dann, wenn ich eine Tabelle benötige.
Diese Tabelle wird dann in der PD eingetragen.
Dann kann ich aber die obige Abfrage nicht machen.

Edit:
Habe mir nochmal Gedanken gemacht und es ist an sich auhc selbstverständlich, dass ich die Tabelle selbst mappen muss, damit ich auf sie zugreifen kann.
Die Frage ist, was kann ich machen, damit ich die Tabelle nicht 1:1 mappen muss?
Ich möchte also dafür sorgen, dass die Tabelle immer im Kernelspace liegt.
Also wie ich sie mappen muss ist mir klar.
Ich verstehe nur nicht, wie ich dann wieder auf sie zugreifen kann.
Ich kann die virtuelle Adresse ja nicht in der PD eintragen
« Letzte Änderung: 08. March 2009, 17:42 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #71 am: 08. March 2009, 19:23 »
Ich habe das ganze mal ein wenig umgeschrieben.
Ich habe mir nun die PD in die PD gemappt und verwende sie als Abbild der PD.
ist das soweit richtig?
Ich mache es jetzt also so, dass ich jede Seite, die ich alloziere gleichzeitig im Abbild auch "alloziere".
Dadurch müssten die Seiten gleich richtig gemappt sein, oder?
Das ganze wirkt aber recht aufwendig und unhandlich.
Deshalb frage ich mich, ob das Konzept passt.

Ist es möglich das so zu machen oder geht es einfacher?

Edit:
Bei meinem Konzept sind mir noch ein Problem eingefallen, auf die ich keine Lösung habe.
Mit der Abbildmethode kann ich nur eine PD abbilden, da das Abbild im Kernelspace liegt und ich dadurch in jeder PD das gleiche Abbild habe (Kernel in jeder PD)
« Letzte Änderung: 08. March 2009, 19:46 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #72 am: 08. March 2009, 23:14 »
Am einfachsten ist es den 1023 Direktory Eintrag, selbst auf die Directory zu zeigen. Dadurch ist jeder ist jede Tabelle automatisch gemappt, wenn du sie in den Direktory reinschreibst.
//Alle Page-Tabels sind nun ab der Position 0xFFC00000 zu finden, und muss nicht extra gemappt werden.
kernel_dir[1023]=(kernel_dir|0x3);
addresse = 0xFFC00000+(i*0x1000);//gib die Addresse des i-ten Tabelle aus, um sie zu bearbeiten.

Ich habe mir noch einmal Gedanken gemacht.
Wie würde ich das denn implementieren, wenn ich nach einer freien Page suche.
Wenn ich in der PD selbst nachschaue bekomme ich einen Pagefault.
Muss ich dann in der PT nachschauen (die an sich die PD ist)?
Das mit der Adressberechnung verstehe ich noch nicht.
An sich schreibe ich doch in die PT-Einträge die physikalischen Adressen der wahren PTs, oder?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #73 am: 11. March 2009, 17:26 »
Wenn ich dich richtig verstanden habe, suchst du nach einer Methode, freie virtuelle Adressen zu suchen.

meinOS macht das so:
'gefunden' = 0
gehe durch PD bis 'gefunden' = 'suche' {
  wenn PDE present dann {
    gehe durch PT {
      wenn PTE present dann {
        'gefunden' = 0
      }
      ansonsten {
        'gefunden'++
      }
    }
  }
  ansonsten {
    'gefunden' += 1024
  }
}
'gefunden' ist eine variable, die die anzahl an zusammenhängenden freien virtuellen pages angibt. 'suche' gibt an, wie viele pages gesucht werden.

Wenn man 1024 PDEs durch hat und immer noch nicht genug, dann sollte man natürlich auch abbrechen... aber dann hat man wohl auch ein problem ;)

Ist wohl nicht das schnellst (ohne caching und so), aber die einfachste methode.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #74 am: 11. March 2009, 21:26 »
Hallo, danke.
Soweit habe ich das Problem mitlerweile gelöst.
Jetzt habe ich nur gerade das Problem, dass ich nicht weiß, wie ich neue PTs eintragen soll.
Ich habe mir folgendes Schema überlegt.
Ich habe die PD an eine bestimmte Stelle in der PD gemappt.
Das mache ich für jeden einzelnen Task.
Wenn ich nun Paging aktiviert habe und herusgefunden habe, dass eine Stelle in der PD keine Tabelle besitzt, kann ich die ja einfach erstellen.
Genau das ist mein Problem.
Ich Interpretiere die PD ja als PD und nun frage ich mich, wie ich die neue PT eintragen kann.

Ein Beispiel zur Verdeutlichung:
Die PD ist an 0x1000 gemappt.
Nun finde ich heraus, dass an 0x2000 keine Tabelle ist.
Diese möchte ich nun erstellen.
Kann ich dann einfach sagen, dass ich an 0x2000 eine PT mit den Flags setze?
Wird diese neue Tabelle dann auch in der "echten" PD gesetzt ist?
Müsste doch an sich, oder?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #75 am: 12. March 2009, 18:30 »
Ja, du schreibst du physische Adresse deiner neu allozierten PT nach 0x1008, also den dritten Eintrag des PDs.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #76 am: 13. March 2009, 00:45 »
Ich wollte noch ein wenig Speicher sparen und habe die gesamte PD auf das letzte Element der letzten Tabelle gemappt.
Das müsste gehen, oder?
Mein Problem ist nur, dass ich einen PF bekomme, wenn ich versuche diese Seite anzusprechen.

Finde den Fehler leider nicht.

create_table(dir , PAGING_TABLE((uint32_t)PAGING_VIRT_DIR_ADDR));
table = (page_table_t)dir[PAGING_TABLE((uint32_t)PAGING_VIRT_DIR_ADDR)];
table[PAGING_PAGE((uint32_t)PAGING_VIRT_DIR_ADDR)] = (uint32_t)dir | PAGING_KERNEL;

void create_table(directory_table_t directory , size_t dir_offset){
page_table_t new_table = (page_table_t)palloc(1);

if(dir_offset <= PAGING_KERNEL_DIR_END)
directory[dir_offset] = (uint32_t)new_table | PAGING_KERNEL;
else
directory[dir_offset] = (uint32_t)new_table | PAGING_USER;

new_table = (page_table_t)directory[dir_offset];
memset(new_table , EMPTY , PAGING_TABLE_SIZE);

invalid_tlb((virt_t)(directory + sizeof(uint32_t) * dir_offset));
}

Der Aufruf findet wie folgt statt:

ret_addr = alloc_pages((directory_table_t)PAGING_VIRT_DIR_ADDR ,
   (virt_t)0x0 , (virt_t)PAGING_KERNEL_MEM_END , size);

Keine Ahnung woran das liegt.
Habe es auch mal gedebuggt aber leider nicht den Fehler gefunden.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #77 am: 13. March 2009, 00:57 »
Wie sparst du Platz? (<- die einzige rhetorische Frage^^) Also man kann maximal eine Page sparen, wenn man self-mapping page tables verwendet. Kann man machen, muss man aber nicht. Vor allem wenn es nicht klappt. ;) Aber irgendwie machst du das auch gar nicht.

Zum Thema:

Weißt du, welche C-Instruktion genau den Page Fault verursacht?

table = (page_table_t)dir[PAGING_TABLE((uint32_t)PAGING_VIRT_DIR_ADDR)];Enthält table dann nicht ein physische Adresse? Ist die garantiert gemappt? Und sind nicht die Flags noch dabei?

Wo kommt da der Aufruf von alloc_pages ins Spiel?
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #78 am: 13. March 2009, 11:27 »
Mir ist der Fehler aufgefallen.
Jetzt funktioniert es.
Trotzdem danke.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

 

Einloggen