Autor Thema: Paging debuggen??  (Gelesen 3100 mal)

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« am: 22. August 2007, 11:24 »
Hi
ich habe mich jetzt mit paging beschäftigt, und habe den code fertig. Natürlich funktioniert noch nichts.
Leider fehlt mir momentan die Idee, wie ich dass debuggen könnte.
Das Problem liegt wahrscheinlich beim erstellen des PageDirectorys bzw der Tables.
Ich könnte jetzt die gesammten Daten per rs232 in eine html-Tabelle schreiben, und kontrolieren, was bei ca 4MB Daten allerdings ein enormer aufwand währe.
Wie habt ihr das gemacht??

Hier einfach mal der Code:
#define SIZEOF_PAGEDIRECTORY (1024*4) ////PD = 1024PT * 4B = 4096
#define SIZEOF_PAGETABLE     (1024*4) ////PT = 1024PF * 4B = 4096
#define SIZEOF_PAGE          (1024*4) ////1 Page-größe (4KB)

#define PG_PRESENT     0x01 //Vorhanden
#define PG_WRITEABLE   0x02 //Speicher auch beschreibbar
#define PG_USERACCRESS 0x04 //Für user zugreifbar (ring3)
#define PG_OUTOFRANGE  0x0200 //Existiert auf Physikalischer ebene nicht (z.B. 17.MB bei 16MB-RAM)
#define PG_REOSDEFAULT (PG_PRESENT | PG_WRITEABLE | PG_USERACCRESS)
#define PG_REOSNULL    (             PG_WRITEABLE | PG_USERACCRESS)

 DWORD *KernelPageDirectory = (DWORD*)0x701000; //Kernelspace (auch virtuell == physikalisch)
 DWORD *KernelPageTables    = (DWORD*)0x702000;

int InitKernelPageDirectory()
{
 int error=0;
 //1024 PageTables einfügen initialisieren
 DWORD currentPT = (DWORD)KernelPageTables;
 DWORD *PageDirectory = KernelPageDirectory;

 for(int i=0; i<1024; i++)
 {
  *PageDirectory = currentPT | PG_REOSDEFAULT;

  error = InitKernelPageTable(currentPT); //Das flag muss mit, um zu wissen, ob spätere tabels present sein müssen oder nicht
  if(error&(~PG_COMPLETE))return error;
  if(error == PG_COMPLETE) break;

  PageDirectory+=4;
  currentPT += SIZEOF_PAGETABLE;
 }

 return 0;

}

int InitKernelPageTable(DWORD PageTable)
{
 static DWORD paddr = 0;
 DWORD flag; //Flags, ob present und son scheiß
 if(paddr < 0xB00000) flag = PG_REOSDEFAULT;          //bis 11MB gehört dem Kernel
 else                {flag = PG_REOSNULL; paddr = 0;} //Danach ist frei und verboten

 //1024 Pages einfügen initialisieren
 for(int i=0; i<1024; i++)
 {
  if(paddr > MaxPhysicalMemory) flag |= PG_OUTOFRANGE; //Wenn die Andresse auserhalb des Vorhanden Arbeitsspeicher liegt

  *(DWORD*)PageTable = paddr | flag; //paddr enthält die physikalische addresse
  PageTable += 4;
  paddr     += SIZEOF_PAGE;
  if(paddr < 0xB00000) flag = PG_REOSDEFAULT;            //bis 11MB gehört dem Kernel
  else                {flag = PG_REOSNULL; paddr = 0;}   //Danach ist frei, und verboten
 }

 if(paddr == 0) return PG_COMPLETE;
 return 0;
}

Das setzten der Register wird wohl richtig sein:
#define CR0_PAGING 0x80000000

//...

 cpu::cr3((DWORD)KernelPageDirectory);
 cpu::cr0(cpu::cr0() | CR0_PAGING);

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 22. August 2007, 12:32 »
  • Warum nicht 4MB-Pages für den Kernelspace? (also von 0 bis 12MB zB)
  • Warum wird der Kernelspace mit PG_USERACCRESS gemappt?
  • Warum erstellst du für den gesammten Adressraum PageTables? Du brauchst doch momentan nur von 0-11MB, oder?
  • Warum machst du dir die Arbeit und gehst jeden Eintrag einzeln durch? Du könntest das pageDir und die pageTables mit memset(bla, 0, 4096) einfach auf 0 setzen und dann das mappen was benötigt wird.
  • Warum ist bei PG_REOSNULL PG_WRITEABLE und PG_USERACCRESS gesetzt? Warum nicht einfach 0?
  • Warum eine statische Variable paddr welche von 0 bis 4GB gehen soll auf 0 setzen wenn sie größer als 0xB00000 ist? Und dann auch noch ständig auf kleiner 0xB00000 prüfen (und danach die flags richten)? :-o

Zum Debuggen: Bochs zeigt dir im Log (wenn man das logging für CPU0 überall auf 'report' setzt) an welcher Code einen Pagefault an welcher Adresse verursacht hat. Dann könntest du einen breakpoint da setzen, dann kommst du in den bochs debugger und kannst dir den inhalt des pagedirectories und der pagetables ausgeben lassen.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #2 am: 22. August 2007, 13:05 »
zu 1 "Warum nicht 4MB-Pages für den Kernelspace? (also von 0 bis 12MB zB)":
Wie mach man den 4MB-Pages?

zu 2 "Warum wird der Kernelspace mit PG_USERACCRESS gemappt?":
Weil jedes tool zugriff auf den Kernel haben soll, und ggf funktionen überschreiben o,ä.
maw.: Alle Macht dem User ;) - Der kernel soll nicht geschützt werden!

zu 3 "Warum erstellst du für den gesammten Adressraum PageTables? Du brauchst doch momentan nur von 0-11MB, oder?":
Mach ich nicht. (s. PG_COMPLETE)

zu 4 "Warum machst du dir die Arbeit und gehst jeden Eintrag einzeln durch?":
s, 3

zu 5 "Warum ist bei PG_REOSNULL PG_WRITEABLE und PG_USERACCRESS gesetzt? Warum nicht einfach 0?":
s, 2. Auch wenn der Speicher nicht reserviert wurde, soll trotzem drauf zugegriffen werden können. (auch wenn es nicht gerade sinnvoll ist)

zu 6 "...":
Ich möchte bis 0xB00000 die Pages "present" machen. Zudem soll beim Kernel die Virtuelle adresse der Physikalischen entsprechen (zumindest der nicht dynamisch reservierte speicher). Nicht presenter speicher, und damit auch nicht reservierter speicher (ich bin mir über die unterschiede im klaren) sollen auf 0x00000000 zeigen

maw.: für einfaches debuggen muss ich bochs installieren...

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 22. August 2007, 13:59 »
Wie mach man den 4MB-Pages?
In cr4 die PSE (= Page Size Extension, bit4) aktivieren. Nun im Page-Directory, wenn du eine 4MB-Page haben willst das PS (= Page Size, bit7) setzen. Dann Zeigt das Page-Directory direkt auf eine Page mit 4MB größe und es kommt keine Page-Table. (Zu beachten ist, dass die 4MB Page ein 4MB align haben muss!)

Zitat
s, 2. Auch wenn der Speicher nicht reserviert wurde, soll trotzem drauf zugegriffen werden können. (auch wenn es nicht gerade sinnvoll ist)
Wenn das PRESENT bit nicht gesetzt ist, kommt ein Pagefault, unabhängig von den anderen Flags. Das ist der Sinn des PRESENT bits.

Zitat
maw.: für einfaches debuggen muss ich bochs installieren...
:?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #4 am: 22. August 2007, 14:19 »
Ok, Dann werde ich mal mit den 4MB Pages arbeiten. Danke

"Wenn das PRESENT bit nicht gesetzt ist, kommt ein Pagefault, unabhängig von den anderen Flags. Das ist der Sinn des PRESENT bits."
:-o Stimmt.  :? Jetzt wüsste ich selber gerne, wass ich mir dabei gedacht habe  :roll:

---

Mein alter Kernel lief nur unter bochs, bei einem echten PC ging nichts. Deshalb teste ich den neuen Kernel nur auf einem echten PC. Zudem ist dann dass loggen über die rs232 leichter (und in echtzeit).
Da ich nun auf linux umgestiegen bin, habe ich bochs garnicht erst installiert.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 22. August 2007, 15:21 »
Zum Debuggen verwende ich immer bochs (wenn der Fehler auch da auftritt). Zum debuggen von so lowlevel zeuchs ist imho bochs unschlagbar. Wenn es dann läuft wird auf qemu, VMWare und 2 reale PCs getestet. Wobei ich auf letzterem im momentan kaum noch teste...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

 

Einloggen