Autor Thema: Initialisieren der Bitmap will nicht  (Gelesen 8432 mal)

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« am: 09. February 2010, 04:12 »
Hallo,
ich habe den Kernel aus der "OS-Dev für Einsteiger" Serie nachprogrammiert und bin nun dabei ihn etwas zu erweitern. Nur irgendwie funktioniert das Initialisieren der Bitmap für die Speicherverwaltung nicht richtig.

void pmm_init(struct multiboot_info* mb_info)
{
    struct multiboot_mmap* mmap = mb_info->mbs_mmap_addr;
    struct multiboot_mmap* mmap_end = (void*)
    ((uintptr_t) mb_info->mbs_mmap_addr + mb_info->mbs_mmap_length);


    /* Per Default ist erst einmal alles reserviert */
    memset(bitmap, 0, sizeof(bitmap));

    /*
     * Nur, was die BIOS-Memory-Map als frei bezeichnet, wird wieder als frei
     * markiert
     */
    while (mmap < mmap_end) {
       if (mmap->type == 1) {
            /* Der Speicherbereich ist frei, entsprechend markieren */
            uintptr_t addr = mmap->base;
            uintptr_t end_addr = addr + mmap->length;

            while (addr < end_addr) {
                pmm_free((void*) addr);
                addr += 0x1000;
            }
        }
        mmap++;
    }

    /* Den Kernel wieder als belegt kennzeichnen */
    uintptr_t addr = (uintptr_t) &kernel_start;
    while (addr < (uintptr_t) &kernel_end) {
        pmm_mark_used((void*) addr);
        addr += 0x1000;
    }
}

Es handelt sich hierbei um die originale Funktion aus dem Tutorial. Ich hab nach ein paar Tests herausgefunden, dass mmap_end immer kleiner ist als mmap, somit wird nie in die while-Schleife gegangen und der vorher als belegt gekennzeichnete Speicher wieder freigegeben.

Ich verstehe ehrlich gesagt nicht wirklich woran das liegen kann, aber vielleicht ist es auch einfach zu spät in der Nacht  :wink:

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #1 am: 09. February 2010, 12:17 »
Warum konvertierst du denn die Adresse in einen void-pointer? Wenn, dann sollte das in einen Zeiger der Struktur umgewandelt werden.
 
Weiterhin würde ich beim Vergleichen der beiden Variablen (mmap und mmap_end) diese jeweils in Ganzzahlen konvertieren, zumindest mache ich das so.

btw. Man kann das auch in einer for-Schleife lösen... :D

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 09. February 2010, 13:52 »
Zitat
Warum konvertierst du denn...
Wie gesagt es ist der original Quelltext aus dem Tutorial  :wink:

Hab mal deine Kritikpunkte umgesetzt, aber das Problem besteht immer noch. Ich habe vor die Schleife noch ein kprintf("%d %d",(unsigned) mmap, (unsigned) mmap_end); geschrieben.

Dabei beträgt mmap 4026597203
       und mmap_end 3758227110.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 09. February 2010, 14:17 »
Die Adressen sind ganz sicher falsch. Lass dir mal mb_info, mb_info->mbs_mmap_addr und mb_info->mbs_mmap_length am Anfang des Kernels und in der Funktion ausgeben. Probleme könnten folgende sein:
* Du hast die Multibootstruktur falsch definiert
* Du veränderst den Pointer auf die Multibootstruktur irgendwo oder du übergibst den falschen
* Du überschreibst die Multibootstruktur von GRUB irgendwann
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

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 09. February 2010, 14:57 »
sowohl am Anfang des Kernels als auch am Anfang der Funktion sind die Werte:
mb_info: 0
mb_info->mbs_mmap_addr: 4026597203
mb_info->mbs_mmap_length : 4026597203

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 09. February 2010, 15:10 »
mb_info: 0
Das ist komplett kaputt. Entweder dein Bootloader ist nicht multibootkompatibel oder du übergibst dem Kernel den falschen Parameter. Was hast du den an der start.S was verändert bzw. wie sieht deine start.S aus? So wie ich das sehe wird das im Tutorial nirgends gezeigt, wie die dann auszusehen hat... ah doch im Teil 7 wird das wohl erklärt.
« Letzte Änderung: 09. February 2010, 15:13 von bluecode »
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

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 09. February 2010, 15:54 »
Meine Start.S ist hier:
.section multiboot
#define MB_MAGIC 0x1badb002
#define MB_FLAGS 0x0
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)

// Der Multiboot-Header
.align 4
.int    MB_MAGIC
.int    MB_FLAGS
.int    MB_CHECKSUM

.section .text

// Init ist eine Funktion aus init.c
.extern init

// _start muss global sein, damit der Linker es findet und als Einsprungspunkt
// benutzen kann (alle Labels, die nicht global sind, sind nur in dieser Datei
// sichtbar)
.global _start
_start:
    // Stack initialisieren
    mov $kernel_stack, %esp

    // C-Code aufrufen und Multiboot-Infostruktur als Parameter uebergeben
    push %ebx
    call init

    // Falls wir jemals aus init zurueckkommen sollten, gehen wir in eine
    // Endlosschleife
    jmp .

// 8 kB Stack fuer den Kernel. Das Label steht hinter dem freien Speicher,
// weil der Stack nach unten waechst
.section .bss
.space 8192
kernel_stack:

Allerdings hab ich das fertige Paket geladen und musste daher auch nix in der Start.S ändern(dachte ich jedenfalls). Die Änderung ist doch nur das PUSH bevors in den C-Kernel geht.

Die Änderungen am Linkerskript wurden auch erledigt.

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 09. February 2010, 19:20 »
Jetzt habe ich nochmal das komplett fertige Tutorial aus dem Netz geladen und versucht Speicher dynamisch anzufordern. Es tritt trotzdem der selbe Fehler auf. Wenn ich jetzt davon ausgehe, dass in dem Tutorial kein Fehler ist, dann könnte vielleicht GRUB das Problem sein?
Ich benutze GRUB-Version 0.97

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 09. February 2010, 20:23 »
Wie sehen deine Änderungen gegenüber tutorial.git (ich nehme an, das meinst du) denn genau aus? Am geschicktesten wäre es vermutlich, wenn du das hier in Patchform postest.

Oder tut es bei dir schon in der unveränderten Originalfassung nicht?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #9 am: 09. February 2010, 21:44 »
Die Multibootflags dürften falsch sein.
Wenn du die Memory Map von GRUB oder zumindest mem_lower und mem_upper nutzen willst, musst du Bit 1 in den Flags setzen. Und wenn ich jetzt nicht völlig daneben liege, sollte das funktionieren, wenn du das wie folgt abänderst:
#define MB_FLAGS (1<<1)

Ich hoffe, dass ich dir damit weiterhelfen konnte. :)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 09. February 2010, 22:51 »
*argh* Ich fürchte, du hast recht. ;)

Hm, das würde wohl heißen, dass ich den Kernel nie über ein Floppyimage und GRUB gebootet habe, sondern nur über qemu. Und dass ich möglicherweise den Multiboot-Code in qemu fixen sollte...
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 09. February 2010, 23:01 »
Also ich hab nochmal ne ganze Weile gefriemelt. Teilweise scheint es mit dem originalen tutorial.git zu funktionieren. Nur liefert pmm_alloc(), wenn es in der init.c (also dem "Hauptprogramm") aufgerufen wird immer einen NULLZeiger zurück.

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #12 am: 10. February 2010, 10:45 »
Dann dürfte wohl kein freier Speicher mehr da sein.  :roll:
 
Was hast du an dem Code alles verändert? Es wäre für mich einfacher, wenn du deinen Code mit den Änderungen in Form eines Zip-Archivs o.ä. mal hochlädst. :)

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 10. February 2010, 11:46 »
Wie gesagt das Problem tritt auch mit dem originalen tutorial.git auf (http://git.tyndur.org/?p=tutorial.git;a=snapshot;h=b150439d3a6158a403f4dfef5d6f55fa6b7434f9;sf=tgz). Und dass kein Speicher da ist kann nicht stimmten denn wenn ich etwas später die init_multitasking() Aufrufe, bekommen alle task auch ihren Speicher nur wenn pmm_alloc() direkt aus der init()-Funktion aufgerufen wird funktioniert es nicht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 10. February 2010, 22:41 »
Also ich hab nochmal ne ganze Weile gefriemelt. Teilweise scheint es mit dem originalen tutorial.git zu funktionieren. Nur liefert pmm_alloc(), wenn es in der init.c (also dem "Hauptprogramm") aufgerufen wird immer einen NULLZeiger zurück.
Hm, rufst du pmm_alloc() auch mehrmals auf? Weil beim ersten Mal ist es eigentlich klar, dass 0 die erste freie Adresse ist. ;) Beim zweiten Mal kriege ich korrekt 0x1000 (oder wenn ich es erst hinter init_multitasking aufrufe, 0xc000 und 0xd000).
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 10. February 2010, 23:23 »
Nein, ich habe es bislang nur einmal aufgerufen, aber am Ende der pmm_alloc() steht:     /* Scheint wohl nichts frei zu sein... */
    return NULL;
also heißt das, dass er keinen freien Speicher gefunden hat, wenn ein NULL-Zeiger zurückgegeben wird (oder bedeutet NULL auch die Adresse 0x00?).

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #16 am: 10. February 2010, 23:25 »
NULL ist in C meist als ((void *)0) definiert (oder einfach nur als 0), also ist NULL==(void *)0==(void *)0x00000000, ja.

dave-g86

  • Beiträge: 9
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 10. February 2010, 23:32 »
Oh danke, wieder was gelernt, der Tag war also nicht umsonst  :-)

 

Einloggen