Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: s137 am 03. December 2014, 19:04

Titel: Verständnisfrage zu Paging
Beitrag von: s137 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
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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).
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 03. December 2014, 22:55
Ah ok danke, werd mal veruchen das erstmal so zu implementieren.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: gale 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...
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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...
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: OsDevNewbie 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:
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 10. December 2014, 09:56
"Dynamisch angelegt" heißt letztendlich "alles, was pmm_alloc() benutzt".
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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. ;)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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...
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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..
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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. ;)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 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?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin 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.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: streetrunner am 11. December 2014, 19:35
Wo wir schon dabei sind: Wie machen das eigentlich die "großen" Betriebssysteme?

Gruß,
Streetrunner
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 11. December 2014, 21:57
ok ich weiß noch nicht genau ob ich das verstanden habe.. ich denke aber schon.. könntest du mir dazu nur ein kleines Beispiel geben?

Wäre sehr nett..
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 11. December 2014, 22:36
Was aber vor allem für mich noch ein Problem darstellt, ist, wenn ich in der Funktion zum Kontext erstellen, den Kontext dynamisch initialisiere, habe ich ja nur eine physische Adresse und kann über die nicht auf den Kontext zugreifen, um darauf zugreifen zu können, müsste ich ihne zuerts in einen anderen Kontext mappen, was irgendwie dann aber auch keinen Sinn machen würde...
Titel: Re: Verständnisfrage zu Paging
Beitrag von: OsDevNewbie am 11. December 2014, 23:48
Ein Beispiel:
Du lässt den letzten Eintrag im PD auf die PD selber zeigen (d.h. es steht dort im Prinzip das selbe wie im CR3).
Dann kannst du über folgende Addresse deine PD bearbeiten: 0xFFFFF000.
Die einzelnen PTs kannst du über folgende Addresse bearbeiten: 0xFFC00000 + (Index des PT << 12).

Somit kannst du dann auch ganz einfach deine Paging Tabellen bearbeiten und auch deine Kontext mappen (dabei suchst du dir eine freie virtuelle Addresse und bearbeitest dann den entsprechenden Eintrag).

Ich hoffe ich konnte dir helfen.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 11. December 2014, 23:50
Was aber vor allem für mich noch ein Problem darstellt, ist, wenn ich in der Funktion zum Kontext erstellen, den Kontext dynamisch initialisiere, habe ich ja nur eine physische Adresse und kann über die nicht auf den Kontext zugreifen, um darauf zugreifen zu können, müsste ich ihne zuerts in einen anderen Kontext mappen, was irgendwie dann aber auch keinen Sinn machen würde...
Ja, wenn du Mappings für ein anderes als das aktive PD ändern willst, musst du in der Regel ein temporäres Mapping für die entsprechenden Page Tables machen.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 11. December 2014, 23:57
Ein Beispiel:
Du lässt den letzten Eintrag im PD auf die PD selber zeigen (d.h. es steht dort im Prinzip das selbe wie im CR3).
Dann kannst du über folgende Addresse deine PD bearbeiten: 0xFFFFF000.
Die einzelnen PTs kannst du über folgende Addresse bearbeiten: 0xFFC00000 + (Index des PT << 12).

Achso ok, jetzt denke ich wird mir das ein bisschen klarer. Aber wenn ich das so richtig verstanden habe, geht das nur wenn der Kontext, also das Pagedirectory aktuell geladen ist oder?

Ja, wenn du Mappings für ein anderes als das aktive PD ändern willst, musst du in der Regel ein temporäres Mapping für die entsprechenden Page Tables machen.

Da liegt aber genau mein Problem.. wie setzte ich so ein temporäres Mapping genau auf? Theoretisch ist es mir klar, aber praktisch hab ich da irgendwie noch so meine Probleme..
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 00:07
Ok, ich hab grade rausgefunden, dass der Ansatz den ich ursprünlich hatte, gar nicht so falsch war wie er für mich ausgesehen hat... Mein Ansatz

#define CURENT_PD     1023 * 1024 + 1023 * PAGE_SIZE // 0xFFFFF000

ergibt bei einer PAGE_SIZE von 4096 nämlich genau die Adresse die du in dem Beispiel genannt hast, aber ich dachte irgendwie dass ich da was anderes gemacht habe, als das was du beschrieben hast. Ich dachte dass dann der letzte PT auf mein PD zeigt, was ja eigentlich aber nichts anderes ist, als der letzte Eintrag des PD's... sollte man eigentlich durch ein bisschen nachdenken draufkommen.

Jetz muss ich nur noch rausfinden wie ich das mit den ganzen (temporären) Mappings hinkriege. Danke schonmal :DD
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 00:30
Ich habe es jetzt so gelöst, dass beim aktivieren eines Speicherkontextes, das PD des Kontextes, auch gleich gemappt wird. Allerdings habe ich immernoch ein Problem auf den Speicherkontext selbst zuzugreifen (beim Erstellen) ich kann zwar auf das PD des aktuellen Tasks zugreifen allerdings habe ich nirgends die virtuelle Adresse des Speicherkontextes selbst..

// Kontext erstellen
struct vmm_context* vmm_create_context(void)
{
    struct vmm_context* context = pmm_alloc(); // Dynamisch initialisiert
    int i;

    context->pagedir_phys = pmm_alloc(); // Hier ist der Zugriff über die physische Adresse des Kontextes, der den Pagefault auslöst...

    for (i = 0; i < 1024; i++) {
        context->pagedir_phys[i] = 0; // Hier nochmals...
    }

    return context; // Physische Adresse des Kontextes wird zurückgegeben
}

 

Titel: Re: Verständnisfrage zu Paging
Beitrag von: Jidder am 12. December 2014, 01:04
Sobald du Paging aktiviert hast, musst du alles, was du mittels pmm_alloc() allokierst, mappen bevor du darauf zugreifen kannst. Also technisch gesehen freie Einträge in einer Page Table suchen und dort die eintragen. Das bereits vorgeschlagene Vorgehen einfach in den Page Tables nach einem unbelegten Eintrag herumzusuchen erfüllt diesen Zweck. Wenn du einen unbenutzen Eintrag findest, trägst du die physische Seite (= das Ergebnis von pmm_alloc) sowie die passenden Flags da ein und anhand der Stelle wo du es in der Page Table eingetragen hast, weißt du, was die dazugehörige virtuelle Adresse ist. Diese nutzt du anschließend um dadrauf zuzugreifen.

Es wäre aber vermutlich besser eine Speicher*verwaltung* zu schreiben, die den ganzen Kram abstrahiert. Zum Beispiel, willst du nicht einen x-beliebigen Eintrag nutzen. Du willst eventuell Einträge nur temporär nutzen bzw. mehrfach nutzen. Kompliziert ... (Igitt! Softwareentwicklung, geh weg, ich mach hier Lowlevel!)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 07:51
Ich habe diese zwei Dinge jetzt einfach mal ganz dreist kombiniert. Ist zwar noch etwas unsauber aber ich denke es könnte so funktionieren...

Ich habe jetzt quasi eine Funktion um eine Page zu mappen (und ja ich lasse Doppelmappings zu wenn ich es explizit so will also auf eine gewisse Adresse, ja ich weiß etwas unsauer aber für den Anfang gehts)

Eine Funktion zum Erstellen eines Kontextes, die den zu erstellenden Kontext und das zu erstellende PD temporär in den aktuellen Kontext mappt, das PD mit nullen befüllt und dann die physische Adresse zurückgibt, sowie diese an einer bestimmten virtuellen Adresse speichert.

Eine Funktion zum Aktivieren des Aktuellen Kontexts und mappen des aktuellen PD's.

Eine vmm_alloc, die mithilfe einer anderen Funktion aufeinanderfolgende Pages im Kernel oder Usermemory findet, diese mappt und die Speicheradresse zurückgibt.

Könnte das so funtionieren eventuell?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 12. December 2014, 09:25
Ich glaube, ich würde die Funktion zum Erstellen des Kontexts sowohl die physische als auch virtuelle Adresse zurückgeben lassen anstatt die virtuelle Adresse als Parameter reinzugeben, aber das ist nur, weil ich das angenehmer zu benutzen fände.

Ansonsten könnte das so funktionieren. Nimmt dein vmm_alloc() dann einen Parameter für den Kontext, in dem gemappt werden soll oder ist das nur für den aktiven?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 11:11
Naja stimmt eigentlich, aber ich werde das jetzt erst einmal so ausprobieren, um zu sehen obs so überhaupt funktionieren würde.

Meine vmm_alloc nimmt als Parameter, einen Speicherkontext, die Anzahl der Pages, die zu allokieren sind und die Flags. Aus den Flags lese ich dann ob ich Speicher im Usermemory (U/S Bit gesetzt) oder Speicher im Kernelmemory (U/S Bit nicht gesetzt) reservieren muss. Am Ende gebe ich dann die virtuelle Adresse des allokierten Speicher zurück.

Außerdem verwende ich eine noch eine extra Funktion, die am Anfang den kernel_context erstellt und mit physischen Adressen arbeitet. 
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 18:25
Ich habe das jetzt mal folgendermaßen umgesetzt, ja ich weiß vermutlich extrem unübersichtlich und uneffizient... Aber im Momemnt geht es mir nur um die Funktionalität, die aber leider immernoch nicht gegeben ist.

Woran könnte das liegen... Ich habe schon so ziemlich alles als Fehlerquelle ausgeschlossen.

Mein Log des Pagefaults bei dem er abbricht sieht so aus und im Code ist die Stelle des Abbruchs gekennzeichnet:

Exception: 14 ( Page Fault)
Error Code: 2

ebp: 127164
eip: 10102c (im Code markiert)
cs: 8
eflags: 210006
esp: 4fdc00
ss: 4fcc00

// Kontext erstellen
struct vmm_context* vmm_create_context(void)
{

    struct vmm_context* context = pmm_alloc();
    int i;

    vmm_map_page((void*)((uintptr_t)CURRENT_CONTEXT), NEW_CONTEXT, (uintptr_t) context, PTE_PRESENT | PTE_WRITE);

    struct vmm_context* context_temp = (void*)((uintptr_t)NEW_CONTEXT);

    //Pagedir in gemapptem Kontext initialisieren
    context_temp->pagedir_phys = pmm_alloc();

// Irgendwo hier dazwischen bei einer Assemblerinstruktion gibt es den Page Fault

    // Pagedir in aktuellen Kontext temporaer mappen
    vmm_map_page((void*)((uintptr_t)CURRENT_CONTEXT), TEMP_PAGEDIR, (uintptr_t) context_temp->pagedir_phys, PTE_PRESENT | PTE_WRITE);

    context_temp->pagedir = (void*)((uintptr_t)TEMP_PAGEDIR);

    for (i = 0; i < 1024; i++) {
        context_temp->pagedir[i] = 0;
    }

    // Dauerhaftes Mapping
    // Physische Adresse des Kontextes speichern an bestimmter speicheradresse in sich selbst
    vmm_map_page((void*)((uintptr_t)NEW_CONTEXT), CURRENT_CONTEXT, (uintptr_t) context, PTE_PRESENT |$

    // Physische Adresse des PD's speichern an bestimmter Speicheradresse in sich selbst
    vmm_map_page((void*)((uintptr_t)NEW_CONTEXT), CURRENT_PD, (uintptr_t) context->pagedir_phys, PTE_PRESENT | PTE_WRITE);

    // Temporaere Mappings aufheben
    vmm_unmap_page((void*)((uintptr_t)CURRENT_CONTEXT), TEMP_PAGEDIR);

    return context; // Physische Adresse des Kontextes zurueckgeben

}

Noch eine Erklärung zu den Konstanten:
CURRENT_PD bezeichnet die Speicheradresse des aktuellen PD's wenn es in sich selbst gemappt ist
CURRENT_PT_BASE ist die Basis zur Berechnung der Adressen der PT's (noch nicht benutzt)
CURRENT_CONTEXT ist der aktuelle Kontext in sich sebst gemappt
NEW_CONTEXT wird in "create_context" erstellt und wir dafür benutzt den neu erstellten Kontext im aktuellen zu mappen
TEMP_PAGEDIR ist die Adresse eines temporären Mappings des PD's

#define CURRENT_PD         1023 * 1024 + 1023 * PAGE_SIZE // 0xFFFFF000
#define CURRENT_PT_BASE    0xFFC00000
#define CURRENT_CONTEXT    1023 * 1024 + 1022 * PAGE_SIZE // 0xFFFFE000
#define NEW_CONTEXT        1023 * 1024 + 1021 * PAGE_SIZE // 0xFFFFD000
#define TEMP_PAGEDIR       1023 * 1024 + 1020 * PAGE_SIZE // 0xFFFFC000

Titel: Re: Verständnisfrage zu Paging
Beitrag von: Jidder am 12. December 2014, 18:48
Wie kommst du auf 1023 * 1024 + 1023 * PAGE_SIZE und die anderen Formeln? Das Ergebnis ist eher in der Region von 5000000 aber nicht 0xFFFFF000.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 19:07
Gute Frage, die Formeln sind natürlich falsch, ich hab nur ein Zahlenbeispiel verwendet um sie zu testen, vermutlich hatte ich da Glück ^^ oder ich hab mich da schon verrechnet...

Naja so müsste es gehen, ich teste das mal:

define CURRENT_PD         (1024 * 1024 * PAGE_SIZE) - (1 * PAGE_SIZE) // 0xFFFFF000
#define CURRENT_PT_BASE    0xFFC00000
#define CURRENT_CONTEXT    (1024 * 1024 * PAGE_SIZE) - (2 * PAGE_SIZE) // 0xFFFFE000
#define NEW_CONTEXT        (1024 * 1024 * PAGE_SIZE) - (3 * PAGE_SIZE) // 0xFFFFD000
#define TEMP_PAGEDIR       (1024 * 1024 * PAGE_SIZE  - (4 * PAGE_SIZE) // 0xFFFFC000


Zwar nicht die beste implementierung und nicht sehr dynamisch aber richtig sollte es zumindest sein :DD
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 19:11
Edit: jetzt bekomme ich einen: "Warnung: Ganzzahlüberlauf in Ausdruck [-Woverflow]" was auch immer das ist... vermutllich ist die Konstante zu groß? Also eigentlich gedacht für unsigned int aber zu groß für int... Müssen Konstanten zwingend int sein? Gibt es vielleicht noch eine andere Möglichkeit für mich das zu lösen?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: Jidder am 12. December 2014, 19:28
So ist es. 1024 * 1024 * 4096 = 2^32 -> passt nicht mal mehr in ein unsigned int.

Alternative Methoden die Adresse der letzten Page zu berechen:

(1024 * 1024 - 1) * PAGE_SIZE
oder
((1023 * 1024) + 1023) * PAGE_SIZE
oder verallgemeinert:
((PD_INDEX * 1024) + PT_INDEX) * PAGE_SIZE
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 19:32
Hmm ok...aber das ist doch eine Speicheradresse unter 4GB sprich die sollte nicht großer als 32bit sein oder verstehe ich da was falsch..?

Danke :DD
Titel: Re: Verständnisfrage zu Paging
Beitrag von: Jidder am 12. December 2014, 19:54
Ja, 32-Bit Speicheradressen passen in ein 32-Bit Integer. Die Zahl 2^32 (= 4 GB) passt aber nicht in ein 32-Bit vorzeichenloses Integer, weil dort eben das Maximum 2^32-1 ist.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 20:00
Naja aber es geht ja auch nicht um die Zahl 4GB, alle meine Zahlen liegen ja unter dem Limit 2^32-1... das heißt es müsste doch funktionieren wenn meine Konstanten statt int, unsigned int sein könnten... oder?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 20:01
Edit: kann es sein das bei der Berechnung selbst schon der Overflow auftritt und ich, wenn ich einfach die Methode der berechnung ändere das umgehen kann?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: Jidder am 12. December 2014, 20:04
Ja, in der Berechnung tritt der Overflow auf. Die bereits genannten Alternativen vermeiden das.

Übrigens du verfehlst regelmäßig den Edit-Knopf ;)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 12. December 2014, 20:20
Ah ok danke dann werd ich das später mal ausprobieren^^ Ja ich weiß^^ Das liegt aber nur dran dass ichs grad eilig habe^^
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 14. December 2014, 13:26
Also ich habe das jetzt mal versucht zu kompilieren, und es tritt auch nach mehrmaligen Korrekturversuchen, diese Reihe von Fehlern auf, die ich versucht habe teilweise zu analysieren.

Wenn ich diese Zeile Beispielsweise kompilieren möchte (Zeile 171):

vmm_map_page( (void*) ((uintptr_t) CURRENT_CONTEXT) , NEW_CONTEXT , (uintptr_t) context, PTE_PRESENT | PTE_WRITE );
wobei CURRENT_CONTEXT so definiert ist: #define CURRENT_CONTEXT    (uintptr_t) ((1023 * 1024) + 1022)* PAGE_SIZE) // 0xFFFFE000 und NEW_CONTEXT so: #define NEW_CONTEXT    (uintptr_t) ((1023 * 1024) + 1021)* PAGE_SIZE) // 0xFFFFD000 und context so:  struct vmm_context* context = pmm_alloc();
erhalte ich folgenen Fehler:


vmm.c: In Funktion »vmm_create_context«:
vmm.c:171:5: Fehler: Zu wenige Argumente für Funktion »vmm_map_page«
vmm.c:50:5: Anmerkung: hier deklariert
vmm.c:171:57: Warnung: linker Operand des Komma-Ausdrucks hat keinen Effekt [-Wunused-value]
vmm.c:171:5: Warnung: Anweisung ohne Effekt [-Wunused-value]
vmm.c:171:59: Fehler: expected »;« before »)« token
vmm.c:171:59: Fehler: expected statement before »)« token
vmm.c:171:71: Fehler: expected expression before »,« token
vmm.c:171:71: Warnung: linker Operand des Komma-Ausdrucks hat keinen Effekt [-Wunused-value]
vmm.c:171:92: Warnung: linker Operand des Komma-Ausdrucks hat keinen Effekt [-Wunused-value]
vmm.c:171:71: Warnung: Anweisung ohne Effekt [-Wunused-value]
vmm.c:171:118: Fehler: expected statement before »)« token


Da ich mehrere solcher Zeilen habe, bekomme ich die Fehlerkette mehrmals.

Hier ist die Deklaration der Funktuion in Zeile 50:

int vmm_map_page(struct vmm_context* context, uintptr_t virt, uintptr_t phys, int flags) {

Also das mit den zuwenig Argumenten resultiert daraus, dass der Compiler innherhalb des Funktionsaufruf eine Parameterübergabe, als Kommaausdruck interpretiert, wenn ich das richtig verstehe, ich weiß nur nicht warum...
Titel: Re: Verständnisfrage zu Paging
Beitrag von: MNemo am 14. December 2014, 14:04
In CURRENT_CONTEXT und NEW_CONTEXT hast du jeweils eine ) mehr als du ( hast.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 14. December 2014, 14:52
oh mann.. und ich hab den Fehler immer in der vmm.c gesucht und nicht den kleinsten Blick in die Headerdatei geworfen weil ich dachte des hätte ich schon überprüft... Danke..
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 16. December 2014, 18:18
Also gut, ich bin jetzt grad am überlegen, ob es nicht einfacher wäre, Mappings immer nur für den aktuellen Kontext durchzuführen, weil ich ansonsten irgendwie gar nicht klarkomme. Ich weiß nichtmal ob ich mir bei meiner vmm_map_page die virtuelle oder die physische Adresse des Kontextes übergeben lassen soll... Ich brauche die Physische um in den Kontext zu wechseln, aber die virtuelle um darauf zuzugreifen, dazu muss der Kontext aber im aktuellen Kontext gemappt sein. Das ist mir glaub ich einfach alles zu kompliziert. Gibts da keinen  einfacheren weg, für all das?
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 16. December 2014, 20:41
Doch, ein fertiges OS benutzen statt selber eins schreiben.

Wenn du sowohl physische als auch virtuelle Adresse brauchst, spricht meines Erachtens einiges dafür, einfach beides zu übergeben (oder eine struct, die beides enthält).
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 16. December 2014, 21:24
ok, schion klar ^^ ich meinte jetzt eigentlich nur das Paging, mit dem Rest bin ich eigentlich ziemlich gut klargekommen, bis auf kleine Leichtsinnsfehler, aber das Paging macht mich irgendwie fertig.. aber naja mal schaun wie ich das hinkriege :DD
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 16. December 2014, 21:48
Irgendwann muss wohl jeder erkennen, dass ein einzelnes verregnetes Wochenende nicht ausreicht, um ein OS zu schreiben. ;)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 16. December 2014, 22:58
ja nein das ist mir schon klar, dass das eine Sache auf Jahre ist, aber es geht mir ja auch nicht um den Aufwand, das mit dem Paging sind immernoch eigentlich Verständnisprobleme, die ich einfach bisher nicht hatte, aber ich versuche mir da gerade irgendwie einen Überblick zu verschaffen, des schwierige für mich ist, das Mappen nachdem Paging eingeschaltet ist und quasi alles nur noch über virtuelle Adressen abläuft und ich mich mit Kontexten rumschlagen muss, und evtl etwas mappen muss das nicht im aktuellen Kontext ist... und ich kann ja nicht in der "vmm_map_page" funktion selber etwas temporär mappen, das ergäbe dann ja eine Rekursion. hmm naja hier hab ich noch gewisse Verständnisprobleme, aber ich bin zuversichtlich dass man die irgendwie aus der Welt schaffen kann.
Titel: Re: Verständnisfrage zu Paging
Beitrag von: kevin am 17. December 2014, 09:43
Rekursionen sind nichts böses, solange man sicherstellt, dass sie irgendwann aufhören.

Wenn vmm_map_page() also für aktive PDs direkt das richtige macht und damit die Rekursion abbricht, dann kann ein vmm_map_page() für inaktive PDs ohne weiteres ein temporäres Mapping im aktiven PD anlegen. Deine Rekursionstiefe ist dann maximal zwei, und das ist doch noch recht überschaubar. ;)
Titel: Re: Verständnisfrage zu Paging
Beitrag von: s137 am 17. December 2014, 14:17
oh ok, dann ist das ja gar nicht so schlimm, wie ich mir das vorgestellt habe. Naja dann setz ich mich mal dran :DD