Autor Thema: Verständnisfrage zu Paging  (Gelesen 17330 mal)

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« am: 03. December 2014, 19:04 »
Hallo zusammen,

Ich hätte eine Verständnisfrage bezüglich Paging. Das Tutorial lässt da ja noch einiges offen. Ich habe jetzt mal wie im Tutorial Paging sehr dürftig aufgesetzt und aktiviert. Wenn ich jetzt einen neuen Task starte ruft mein Kernel aber immernoch die pmm_alloc() Funktionen auf um Speicher für den Stack zu bekommen. Jetzt denke ich mal sollte ich eine vmm_alloc() erstellen die ersteinmal mit pmm_alloc() eine physische Speicherseite besorgt und mir dann deren Adresse in das Pagedirectory des Tasks einträgt und dann die Virtuelle Adresse zurückgibt. Sehe ich das schonmal richtig?

Nur wie genau mach ich das dann mit der Vergabe der Virtuellen Adressen, ich kann ja nicht einfach immer irgendeine Adresse hernehmen, da muss ja irgendein System dahinter sein.

s137

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 03. December 2014, 22:31 »
Das klingt schonmal nach einem sinnvollen Ansatz, ja. :)

Du nimmst nicht irgendeine virtuelle Adresse her, aber fast: Irgendeine freie. Je nach Komplexität deines VMM wirst du am Anfang wohl erst einmal einfach direkt in den Page Tables nachschauen, wo etwas frei ist. Später könnte es dir eventuell passieren, dass du nochmal eine separate Datenstruktur für den VMM brauchst, aber du kommst ohne ziemlich weit (týndur hat zum Beispiel auch noch keine).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 03. December 2014, 22:55 »
Ah ok danke, werd mal veruchen das erstmal so zu implementieren.

gale

  • Beiträge: 10
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 04. December 2014, 15:24 »
Oh danke Kevin, das sind auch für mich neue Informationen. Lerne das Forum jetzt schon schätzen und lieben hehe...
Signaturen werden unter jedem Beitrag und jeder Privaten Mitteilung angezeigt. In der Signatur können Smileys und BBCode verwendet werden.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 04. December 2014, 17:19 »
Was genau meinst du eigtl mit "seperater Datenstruktur für den VMM"? Und ich habe irgendwie noch nicht ganz verstanden wie ich das mit der Aufteilung von Kernel und Userspace mache ( hätte gern 0-1GB Kernel, 1-4GB Userspace) und dann den Kernel vollstandig in jeden Prozess mappe und das immer gleich... irgendwie blick ich da nicht ganz durch...
« Letzte Änderung: 04. December 2014, 17:22 von s137 »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 05. December 2014, 09:46 »
Mit der separaten Datenstruktur meine ich irgendeine Art von struct page, die mehr Informationen zu einer Page enthalten kann als du in einem Pagetable-Eintrag unterbringst. So etwas könntest du eventuell brauchen, sobald du COW implementierst.

Letztendlich besagt diese Aufteilung nur, dass du, wenn du Allokationen für den Kernel machst, diese immer zwischen 0 und 1 GB - 1 haben willst, und wenn sie für den Userspace sind, von 1 GB bis 4 GB. Deine Funktion, die eine virtuelle Adresse alloziert, muss also am besten einen Adressbereich als Parameter bekommen, in dem sie nach freiem Speicher suchen soll.

Dass der Kernel überall gleich gemappt ist, kannst du dadurch lösen, dass in jedem PD die ersten 256 Einträge gleich sind, d.h. du benutzt überall dieselben Pagetables. Wenn du sie in einem Task änderst, hat der andere Task die Änderung automatisch auch. Aufpassen musst du nur, wenn du einen der ersten 256 PD-Einträge änderst: Dann musst du dafür sorgen, dass alle anderen PDs auch auf den aktuellen Stand gebracht werden.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #6 am: 05. December 2014, 09:51 »
Und ich habe irgendwie noch nicht ganz verstanden wie ich das mit der Aufteilung von Kernel und Userspace mache ( hätte gern 0-1GB Kernel, 1-4GB Userspace) und dann den Kernel vollstandig in jeden Prozess mappe und das immer gleich... irgendwie blick ich da nicht ganz durch...
Die ersten 1 GB virtueller Speicher entspricht den ersten 256 Einträgen im Page Directory. Diese Einträge sind dann einfach im PD von jedem Prozess genau gleich. Natürlich nicht vergessen, bei diesen Einträgen, das U/S Bit zu löschen. Bei den restlichen 768 Einträgen muss das U/S Bit gesetzt sein.

Edit: da war wohl einer schneller als ich  :wink:
« Letzte Änderung: 05. December 2014, 09:55 von OsDevNewbie »
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 05. December 2014, 13:25 »
Zitat von: kevin
Dass der Kernel überall gleich gemappt ist, kannst du dadurch lösen, dass in jedem PD die ersten 256 Einträge gleich sind, d.h. du benutzt überall dieselben Pagetables. Wenn du sie in einem Task änderst, hat der andere Task die Änderung automatisch auch. Aufpassen musst du nur, wenn du einen der ersten 256 PD-Einträge änderst: Dann musst du dafür sorgen, dass alle anderen PDs auch auf den aktuellen Stand gebracht werden.

Diese Aussage habe ich noch nicht ganz verstanden... wenn ich in jedem Pagedirectory dieselben ersten 256 Pagetables verwende, und darin was verändere...haben dann die anderen Tasks auch automatisch diese Änderung...oder muss ich das dann irgendwie manuell kopieren.?..eigtl müssten doch die Änderung alle haben, in den PD Eintragen steht ja immer die Speicheradresse der selben Pagetables oder?

Und OsDevNewbie, meinst du mit U/S Bit das Userspace Bit?
« Letzte Änderung: 05. December 2014, 13:27 von s137 »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 05. December 2014, 14:07 »
Wenn du einen PT-Eintrag änderst, kriegen es alle automatisch, weil sie ja auf dieselbe PT verweisen. Wenn du einen PD-Eintrag änderst, musst du dich selber drum kümmern, dass es überall ankommt.

Und ja, U/S (User/Supervisor) ist der offizielle Name für das Userspace-Bit, wie ihn das Intel-Manual benutzt.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 09. December 2014, 19:53 »
ah ok, das habe ich verstanden, danke, habe jetzt auch schonmal eine primitive vmm_alloc() aufgesetzt nur bei der Initialisierung der VMM fehlt noch ein bisschen was...

Bis jetzt habe ich in etwa das:

// VMM initialisieren
void vmm_init(void)
{
    uint32_t cr0;
    int i;
    int x;

    // Symbole am Anfang und Ende aus pmm.c holen
    uintptr_t kernel_start_addr = getKernelStart();
    uintptr_t kernel_end_addr = getKernelEnd();

    kernel_context = vmm_create_context();

    // Kernelcode mappen
    while (kernel_start_addr < kernel_end_addr) {
      vmm_map_page(kernel_context, KERNEL_BASE + x * PAGE_SIZE, kernel_start_addr, PTE_PRESENT | PTE_WRITE);
      kernel_start_addr += 0x1000;
      x++;
    }

    // Videospeicher mappen
    for (i = 0xB8000; i < 0xC0000; i += 0x1000) {
        vmm_map_page(kernel_context, i, i, PTE_PRESENT | PTE_WRITE);
    }


Hier fehlt jetzt noch der Teil: "Zum Zeitpunkt der Paging-Initialisierung schon dynamisch angelegte Kerneldaten, z.B. die Bitmap der physischen Speicherverwaltung" Jetzt wollte ich mal fragen was da eigentlich so alles dazugehört außer der Bitmap wenn ich nach dem Tutorial vorgegangen bin und außerdem ob mein Ansatzt schonmal richtig ist oder man da auf Anhieb Fehler entdeckt?

Außerdem wollte ich noch Fragen wie genau man dann z.B. die Bitmap so mappt, dass man nacher dann auch darauf zugreifen kann und wie der Zugriff dann aussehen müsste... irgendwie versteh ich das noch nicht so ganz...

Danke schonmal
s137
« Letzte Änderung: 09. December 2014, 21:08 von s137 »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 10. December 2014, 09:56 »
"Dynamisch angelegt" heißt letztendlich "alles, was pmm_alloc() benutzt".
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 10. December 2014, 14:33 »
Aber das heißt ja dann quasi, dass wenn ich die Bitmap der physische Speicherverwaltung so wie im Tutorial statisch anlege, dass ich sie dann gar nicht zu mappen brauche, oder?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 10. December 2014, 16:40 »
Naja, jedenfalls nicht ein zweites Mal. Sie steckt ja schon zwischen kernel_start und kernel_end.

Aber statische Bitmap will man sowieso nicht haben, finde ich. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 10. December 2014, 16:44 »
Ja ok, das macht sinn. :DD

Naja jetzt für den Anfang ist es ja nicht so schlimm denk ich, oder?
Das lässt sich ja dann später ändern...

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 10. December 2014, 18:43 »
Ich habe jetzt hier schonmal ein Problem (Page Fault -> Page not present):

truct vmm_context* vmm_create_context(void)
{
    struct vmm_context* context = pmm_alloc();
    int i;

    /* Page Directory anlegen und mit Nullen initialisieren */
    context->pagedir = pmm_alloc(); // Zugriff auf context....
    for (i = 0; i < 1024; i++) {
        context->pagedir[i] = 0;
    }

    return context;
}


Wobei ich jetzt mal denke das das daraus resultiert, das Paging schon eingeschaltet ist und ich somit auf den "context" nicht zugreifen kann weil er nicht gemappt ist... Aber wenn ich ihn mappen würde, dann müsste ich ihn ja in einen anderen Kontext mappen...Also am einfachsten temporär in den aktuellen Kontext? Ist das ein brauchbarer ansatz? Das heißt ich müsste noch irgendwie an den aktuelle Kontext kommen...hmm..

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 10. December 2014, 23:09 »
Also gut ich denke ich habe hier grade ein ernsthaftes Verständnisproblem...

Ich blicke nichtmehr durch, wann genau ich mit physischen und wann mit virtuellen Adressen arbeite. Ich weiß zwar dass ich sobald Paging aktiviert ist, nur noch virtuelle Adressen benutzen kann, allerdings weiß ich nicht wie das funktionieren soll... Ich brauche ja dann einerseits die physische Adresse des Pagedirectorys sowie des Speicherkontextes für den Kontextwechsel, und auch die virtuelle Adresse von beidem um darauf zuzugreifen, und z.B. meine Mappings zu verändern. Wenn ich dann z.B. die Funktion zum Kontext erstellen so belasse wie im Tutorial beschrieben, dann funktioniert diese genau einmal und zwar bei der Initialisierung des VMM beim Erstellen des kernel_context, danach kann ich keinen neuen Kontext mehr erstellen, weil ich ihm ja eine physische Adresse zuweisen muss und durch diese aber nicht darauf zugreifen kann. Würde ich den Kontext dann aber mappen wolllen, müsste ich ihn ja wieder in einen anderen Kontext mappen, den ich aber nicht zur Vefügung habe, bzw. auf den aktuellen bezogen, von dem ich auch keine virtuelle Adresse habe.

Also irgendwie fehlt es da bei mir an Grundverständnis.. wenn mir das irgendwer erklären könnte, wie das was ich vorhabe realisierbar ist, wäre ich sehr dankbar.

Viele Grüße
s137

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 11. December 2014, 00:06 »
Es spricht nichts dagegen, die Page Tables des aktiven Kontexts in diesem auch gemappt zu haben.

Der übliche Trick, der allerdings am Anfang ein bisschen schwer zu verstehen sein kann, ist, dass man einen PD-Eintrag wieder auf das PD selbst verweisen lässt. Du kannst ja mal versuchen, dir zu überlegen, welchen Effekt das hat. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

s137

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 11. December 2014, 11:54 »
Danke schonmal,

Naja der Effekt wäre dann, dass die einzelnen Einträge des PD's als Pagetables gemappt werden. Aber ich weiß immernoch nicht ganz was das bringen soll... Um darauf zuzugreifen, bräuchte ich ja die virtuelle Adresse eines Kontextes, mit der physischen kann ich ja außer einem Kontextwechsel nichts anfangen, oder verstehe ich da noch was falsch?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 11. December 2014, 11:59 »
Ich weiß nicht, ob das ist was du gemeint hast, aber der Effekt ist, dass dein PD als Page Table interpretiert wird und dadurch alle deine PTs (und auch das PD selber) die Pages sind, die diese Page Table mappt. Du hast damit also eine (sogar einfach berechenbare) virtuelle Adresse für jede aktive Page Table, die du ändern willst.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 11. December 2014, 19:35 »
Wo wir schon dabei sind: Wie machen das eigentlich die "großen" Betriebssysteme?

Gruß,
Streetrunner

 

Einloggen