Autor Thema: Paging  (Gelesen 23059 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 16. December 2008, 17:53 »
Nabend zusammen,

ich bin eben dabei jetzt paging einzubauen.
Dabei sind mir ein paar Fragen gekommen.
Wie arbeiten denn die physikalische und die virtuelle Speicherverwaltungen zusammen?
Wenn ich das richtig verstanden habe, ist Paging komplett unabhängig von der physischen Verwaltung.
Wenn ja, wozu brauche ich dann eine physikalsche Verwaltung?
Gut ok, damit kann ich die Module etc nachladen, aber das könnte ich ja auch anders realisieren.
Allerdings ist eines ein ganz großes Fragezeichen:
Wenn ich mir eine virtuelle Verwaltung aufbaue, liegt die doch im RAM, oder liegt die im Prozessorcache?
Müsste ich nicht bei der Erstellung der Virtuellen Verwaltung die Pages in der physischen Verwaltung anmelden?
Ich habe auch gelesen, dass ich bestimmte physische Speicherbereiche in den virtuellen Bereich mappen kann.
Das wäre doch dann zum Beispiel für den VGA-Block nützlich, oder?
Wie würde das denn dann aussehen?
Ich kann ja nur noch über virtuelle Adressen daran kommen.
Oder mappe ich den vor dem aktivieren des Paging-Mechanismusses?

Das waren jetzt so die Fragen, die mir auf anhieb gekommen sind.
Da folgen bestimmt noch einige.

Danke.

Gruß
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 16. December 2008, 18:31 »
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 16. December 2008, 21:16 »
Ok, danke.
Habe ich übersehen....
Nun habe ich trotzdem noch eine Frage.
Wenn ich eine Seite mappen möchte, erstelle ich als erstes eine Directory die dann mit einer Table_Page zusammenarbeitet, oder wie?
Dann habe ich mir mal den Code von LOST angeschaut und bei map_page oder so nur Bahnhof verstanden.
Wieso mappt ihr eine neue Adresse erst in den Kernel-Bereich?
reicht es nicht aus, wenn man eine Directory und eine Table hat?
Man kann doch den Unterschied zwischen Kernel und User mit dem Flag realisieren.
Dann könnte man noch unter Umständen abfragen, ob ein Bereich schon beschrieben ist, wenn ja dann einen Panic auslösen oder beim Multitasking denjenigen der Requested abschießen.
Und wenn der noch nicht besteht einfach einen neuen erzeugen.
Wenn es sich dann dabei um einen Kernelaufruf einfach den Usermode nicht mit einschalten.

Ich finde eure Variante ein wenig zu kompliziert, es sei denn ich habe das mit dem Paging noch nicht richtig verstanden.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 17. December 2008, 00:06 »
Habe mal versucht mein Paging zu implementieren.
Leider funktioniert das Mappen des GraKa-Speichers nicht.
Der Code soeht wie folgt aus:
size_t video_size = 80 * 25 * 2 / BLOCK_SIZE + 1;
map_paging_range((physaddr_t)0xB8000 , (virtaddr_t)0xB8000 , PAGING_PRESENT | PAGING_WRITEABLE , video_size);

Dazu dann noch die Methode, die mappen soll:
    paging_table_t paging_table;
    dword virt_page = (dword)vaddr;

    if(vaddr == NULL)
        panic("Illegal call to the NULL-Table-Entry");

    if(flags & ~0x01F)
        return;

    if(((dword)vaddr | (dword)paddr) && 0xFFF)
        panic("The requested address is not 4k-aligned");

    //page does not exist
    if((paging_directory[virt_page / PAGING_TABLE_SIZE] & PAGING_NOTTLB) == 0 ){
        paging_table = (paging_table_t)phys_alloc(sizeof(paging_table_t));

        paging_directory[virt_page / PAGING_TABLE_SIZE] = ((dword)paging_table) | flags;

        memset(paging_table , 0 , BLOCK_SIZE);
    }

Es wird folgender Panic ausgelöst:
The requested address is not 4k-aligned

Woran kann das liegen?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 17. December 2008, 09:28 »
Du willst in der if-Abfrage das bitweise Und (&) verwenden, nicht das logische Und (&&).
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 17. December 2008, 17:18 »
Danke.
Nun habe ich leider ein anderes Problem.
Wenn ich alles gemappt habe und dann das Paging aktivieren möchte, bekomme ich beim qemu ein triple fault.
Das liegt daran, dass ih cr0 das 31-Bit setze.
Leider kann ich mir nicht erklären.
Was mir aufgefallen ist, ist dass wenn ich zwei debug-ausgaben mache, dass meine page-directory auf 0x0001090 oder so zeigt und der Eintrag in dem cr3 Register auf 0x0001027 oder so.
Woran kann das liegen?
Ist das der Grund für meinen triple fault?

Leider funktioniert bei mir bochs nicht (findet die VGA-Bibliothek nicht), deshalb kann ich damit leider nicht debuggen und das Debugging beim qemu will bei mir nicht so richtig laufen...

Danke für eure Hilfe.

Gruß
rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 17. December 2008, 18:32 »
Was mir aufgefallen ist, ist dass wenn ich zwei debug-ausgaben mache, dass meine page-directory auf 0x0001090 oder so zeigt und der Eintrag in dem cr3 Register auf 0x0001027 oder so.
Woran kann das liegen?
Ist das der Grund für meinen triple fault?
Vermutlich ja. cr3 sollte auf 0x1000 aligned sein. Aber dein geposteter Code zeigt leider nicht, was du beim Initialisieren genau machst.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 17. December 2008, 18:48 »
Das ist der initialisierende Code:

paging_directory = (paging_directory_t)phys_alloc(PAGING_DIRECTORY_SIZE);
    memset(paging_directory , 0 , BLOCK_SIZE);
    paging_directory[PAGING_VIRTADDR >> PAGING_DIR_SHIFT] = (dword)paging_directory | PAGING_PRESENT | PAGING_WRITEABLE;
    size_t kernel_size = ((dword)kernel_end - (dword)kernel_start) / BLOCK_SIZE;
    map_paging_range(kernel_start , kernel_mem_start , PAGING_PRESENT | PAGING_WRITEABLE | PAGING_NOTTLB , kernel_size);
    size_t video_size = 80 * 25 * 2 / BLOCK_SIZE + 1;
    map_paging_range((physaddr_t)0xB8000 , (virtaddr_t)0xB8000 , PAGING_PRESENT | PAGING_WRITEABLE , video_size);
    map_paging(paging_directory , paging_directory , PAGING_PRESENT | PAGING_WRITEABLE);
    map_paging_range(bitmap_start , bitmap_start , PAGING_PRESENT | PAGING_WRITEABLE , bitmap_length / BLOCK_SIZE);
    //enable paging
    _write_cr3((dword)&paging_directory);
    _write_cr0(_read_cr0() | 0x80000000);

Wieso soll cr3 aof 0x1000 zeigen?
Meintest du nicht er 0x1090?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 17. December 2008, 19:08 »
    _write_cr3((dword)&paging_directory);
Da ist schonmal das & zuviel. paging_directory ist doch schon ein Pointer.

Zitat
Wieso soll cr3 aof 0x1000 zeigen?
Meintest du nicht er 0x1090?
Öhm, nein. Wo sollte die 9 herkommen?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 17. December 2008, 19:11 »
Ok stimmt.
War vorher auch nicht da...
Wieso soll es auf 0x1000 zeigen?
Das muss doch dahin zeigen, wo meine Directory liegt, oder?
Aber ich alloziere mir ja Speicher dieser Größe und wer sagt mir, dass das Teil bei 0x1000 liegt?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #10 am: 17. December 2008, 19:24 »
taljeth hat ja nicht gesagt, dass das auf 0x1000 zeigen müsse. Die Adresse die du da reinschreibst muss halt auf 0x1000 Bytes ausgerichtet sein, d.h. ein Vielfaches davon sein.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 17. December 2008, 19:27 »
Das bedeutet, dass meine Page-Directory an einer anderen stelle liegen muss, oder wie?
Also bei 0x2000, etc.
Aber wie mache ich das am besten mit meiner physikalischen Speicherverwaltung?
Die gibt mir ja vor, wo das alles zu liegen hat.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 17. December 2008, 19:35 »
Ganz einfach: Die gibt dir 4k-Pages, also ist automatisch alles auf 0x1000 ausgerichtet.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 17. December 2008, 19:37 »
Aber wieso liegt meine page-directory dann bei 0x1090, dann müsste die ja verbugged sein, oder?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 17. December 2008, 20:01 »
Sieht grad so aus.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 17. December 2008, 22:55 »
Ok.
Das Problem mit dem physischen Speichermanagment habe ich behoben (scheint zumindest so).
Leider bekomme ich bei der Benutzung des Pagings immer noch den triple fault.
Die Adresse, die jetzt im cr3-reg steht sieht nun besser aus:
0x10C000.
Aber woran kann es nun liegen, dass es den Triple fault gibt?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 18. December 2008, 01:12 »
Wenn du wissen willst, auf welche Adresse er zugegriffen hat, kannst du qemu mal mit -d int starten. In der /tmp/qemu.log findest du dann alle Interrupts, die ausgelöst worden sind. Kurz vor dem Ende müßte ein 0e kommen (Page Fault) und beim zugehörigen CPU-Dump steht die schuldige Adresse in cr2. Und dann kannst du versuchen, rauszufinden, warum diese Adresse nicht gemappt ist.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 18. December 2008, 19:36 »
Die Ausgabe des Logs ergab folgendes:
check_exception old: 8 new e
qemu: fatal: triple fault
EAX=e0000011 EBX=00001000 ECX=00000000 EDX=00031000
ESI=00000001 EDI=00000001 EBP=00107f68 ESP=00107f68
EIP=0010271d EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300
CS =0008 00000000 ffffffff 00cf9a00
SS =0010 00000000 ffffffff 00cf9300
DS =0010 00000000 ffffffff 00cf9300
FS =0010 00000000 ffffffff 00cf9300
GS =0010 00000000 ffffffff 00cf9300
LDT=0000 00000000 0000ffff 00008000
TR =0000 00000000 0000ffff 00008000
GDT=     00009108 00000027
IDT=     00000000 000003ff
CR0=e0000011 CR2=00000040 CR3=0010c000 CR4=00000000
CCS=0000000c CCD=e0000011 CCO=LOGICL 
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000

Da steht leider nichts von 0e oder ich gucke falsch.
Aber was mich wundert ist cr2. Da dürfte er gar nicht hin.
Da wird nichts gemappt.
Soll es auch nicht.
Wie kann ich denn am besten mit dem qemu debuggen?
Also wie füge ich Breakpoints und so ein?
Habe mal gegoogelt aber leider kein ordentliches Tut gefunden.
Was ist besser zum debuggen?
Boch oder QEMU?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 18. December 2008, 21:27 »
Für die lowleveligeren Sachen am Anfang ist bochs vermutlich besser. Ansonsten bin ich überzeugter qemu-Anhänger. ;)

In der Log mußt du noch ein Stück zurück. Vor dem Triple Fault kommt ein Double Fault (das ist die 8 ) und davor müßte der Page Fault kommen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 18. December 2008, 21:35 »
Kannst du mir dann vllt erklären, warum mein Boch die VGA-Bibliothek nicht findet?
Was mussen ich denn da alles noch mit installieren.
Benutze Ubuntu 8.04.

Da steht dann nur noch
check_exception old: ffffffff new e
check_exception old: e new e

Ist der erste die page fault exception?
Die Exceptions werden doch nicht deaktiviert, oder?
Also wenn ich die Interrupts deaktiviert habe.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

 

Einloggen