Autor Thema: Tutorial Teil 7: GPF Problem  (Gelesen 8706 mal)

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« am: 28. May 2012, 08:19 »
Beim letzten Mal wars ein Tippfehler, der den GPF ausgelöst hat.
Ich weiß nicht, woran es diesmal liegt...

Ich habe Teil 7 durchgearbeitet und es geht nicht. Erst wusste ich nur, dass ein General Protection Fault ausgelöst wird.
Um mehr zu erfahren, habe ich den Schduler und den generellen Interrupthandler am Anfang, vor jeder Operation und am Ende eine Medung ausgeben lassen.

Und jetzt der kuriose Output:

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #1 am: 28. May 2012, 17:34 »
Wenn ich mir die Werte so ansehe, dann liest du da irgendwo die Registerinhalte von NULL. Und da ESP nur knapp über 0 ist, nehme ich mal an, das wird genau der Punkt sein. Wenn ich also raten müsste, dünkte ich, dass du im Scheduler ESP auf NULL setzt und dann beim Springen in den Task alle Register von dort gelesen werden – was natürlich nicht so doll ist.

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 28. May 2012, 18:26 »
Meine Funktion schedule (ohne Kommentare, etc)
struct cpu_state* schedule(struct cpu_state* cpu) {
    if (current_task != NULL) {
      current_task->cpu_state = cpu;
    }
     if (current_task == NULL) {
         current_task = first_task;
     } else {
         current_task = current_task->next;
         if (current_task == NULL) {
             current_task = first_task;
         }
     }
    cpu = current_task->cpu_state;

    return cpu;
}

Ich glaube nicht, dass ich den Prozessorzustand von NULL lade...

Und müsste mir das Ding nicht --ENTERING handle_interrupt anzeigen?
« Letzte Änderung: 28. May 2012, 18:40 von BeanMe »

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #3 am: 28. May 2012, 19:27 »
Juuut, wenn ich mir das Bild nochmal ansehe, dann tritt der Fehler erst auf, nachdem noch ein B geschrieben wurde. Müsste ich also weiter raten, dann ist vielleicht der Syscallhandler schuld – prinzipiell ist aber ziemlich sicher, dass du irgendwo ESP auf NULL setzt. :wink:

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 28. May 2012, 19:38 »
Was aber nicht erklärt, warum mir kein --ENTERING handle_interrupt angezeigt wird.
Und woher kommt das B? Dass es da ist, hat mich auch schon verwundert...

//EDIT: Es wäre logisch, wenn der Fehler bereits im PMM liegt, dass für Task A nämlich kein Speicher frei ist... Ach so, Blödsinn, Task B wurde ja später reserviert, er wird nur vorher ausgeführt...
//EDIT2: Wäre es nicht logisch, dass das Schreiben ins TSS das ganze auslöst? Aber dann müsste es ja von Anfang an nicht funktioniert haben...
« Letzte Änderung: 01. June 2012, 17:21 von BeanMe »

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 01. June 2012, 17:30 »
Was vielleicht erwähnenswert wäre, ist, dass ich nicht vier, sondern nur zwei Test-Tasks habe.
B wird nach A hinzugefügt, läuft also vorher.

Es ist mir nicht klar, was ESP auf NULL setzt. Mein Hauptverdächtiger ist das PMM, durch dieses wird Platz für einen User Stack reserviert. Was hat das PMM zu seiner Verteidigung zu sagen? "Als ich nicht implementiert werden konnte, hat man mich aus dem Beispiel-Repo kopiert..."
Klasse, jetzt komme ich nicht mehr weiter...

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 02. June 2012, 18:26 »
Bitte, helft mir! Ich komme sonst nicht weiter!

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 02. June 2012, 20:24 »
Code hochladen und verlinken.
Dieser Text wird unter jedem Beitrag angezeigt.

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 05. June 2012, 16:00 »
Als TAR-Archiv zu finden:
http://temp-share.com/show/KdPf3U6Fh

Wenn ihr lieber andere Formate hättet, müsstt ihr es nur sagen.
Der Link gilt bis 5. Juni 2013
« Letzte Änderung: 05. June 2012, 16:02 von BeanMe »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 05. June 2012, 17:05 »
Also das erste Problem ist, dass du das struct für die Multibootinformationen nicht korrekt angelegt hast. Das syms-Feld ist eigentlich 16 Bytes groß, aber bei dir warens nur 8 Bytes. Dadurch waren die Felder für die Memory-Info verschoben, was zur Folge hatte, dass deine physische Speicherverwaltung nicht korrekt initialisiert wurde. Das hatte wiederrum zur Folge, dass die immer 0 zurückgegeben hat, und weil du das nicht abgefangen hast, waren alle deine Tasks an dieser Adresse, und die Überprüfung ob current_task = NULL ist, war immer wahr. Der erste Fix ist also pmm.h zu korrigieren:

...
  uint32_t mbs_mods_addr;
  uint32_t mbs_syms1;
  uint32_t mbs_syms2;
  uint32_t mbs_syms3;
  uint32_t mbs_syms4;
  uint32_t mbs_mmap_length;
  uint32_t mbs_mmap_addr;
...

Dann sind immerhin schon mal die meisten Pointer ungleich 0, aber es tritt immer noch derselbe Fehler auf. Die Ursache dafür ist, dass in init_task die Variablen user_stack und stack nicht groß genug sind. Es sollten Pointer sein.

So muss es aussehen:
   uint8_t *user_stack = pmm_alloc();
   uint8_t *stack = pmm_alloc();


Das hätten dir deine Warnungen sogar sagen können, aber vermutlich hast du die ignoriert, weil es soviele sind. Die meisten Warnungen wirst du übrigens los, wenn du den Code als C99 kompilierst (it dem GCC-Parameter -std=c99 bzw. -std=gnu99, weil du asm statt __asm__ benutzt.).
Dieser Text wird unter jedem Beitrag angezeigt.

BeanMe

  • Beiträge: 19
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 10. June 2012, 08:39 »
Danke! Ich probiere es sofort aus...
Also, auf die Pointer hätte ich selber kommen können, aber das Multiboot-Feld...
Danke!

Es geht!
Jetzt, wo das gelöst ist, denkt man sich, das war einfach, ich hatte vermutlich "ein Brett vorm Kopf".

 

Einloggen