Autor Thema: Mit ein paar Zeilem mehr, streikt der Kernel  (Gelesen 5382 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 14. May 2011, 09:22 »
Morgen zusammen,

ich habe ein Problem mit meinem Kernel. Ich habe mir einen SLAB-Allocator geschrieben, der momentan Slabs fuer allozierbare Caches/Slabs/Objekte erstellt, damit selbst der SLAB-Aufbau moeglichst parallel stattfinden kann. Momentan berechne ich die Anzahl an Objekten, die ich benoetige, damit ich den Speicher moeglichst effektiv verwalten kann.
Meine Formel funktioniert soweit, verschwendet zum Teil nur 300 Byte. Um das zu verhindern, optimiere ich den Speicher danach noch von Hand. Leider spinnt der Kernel, sobald ich ihn mit diesen Optimierungen kompiliere. Woran kann das liegen?

Ohne die Optimierung:
inline void __preboot_text slab_struct_count(size_t* objs, size_t* chunks,
size_t size, size_t alloc) {
size_t tmp;

tmp = alloc - sizeof(struct slab_cache);
tmp /= sizeof(struct slab_chunk) + (sizeof(struct slab_object) + size) *
CONFIG_OBJ_PER_CHUNK;

*chunks = tmp;
*objs = tmp * CONFIG_OBJ_PER_CHUNK;
}

Mit der Optimierung:
inline void __preboot_text slab_struct_count(size_t* objs, size_t* chunks,
size_t size, size_t alloc) {
size_t tmp;
int diff;

tmp = alloc - sizeof(struct slab_cache);
tmp /= sizeof(struct slab_chunk) + (sizeof(struct slab_object) + size) *
CONFIG_OBJ_PER_CHUNK;

*chunks = tmp;
*objs = tmp * CONFIG_OBJ_PER_CHUNK;

diff = alloc - sizeof(struct slab_cache) - tmp * sizeof(struct slab_chunk) -
(tmp * CONFIG_OBJ_PER_CHUNK) * sizeof(struct slab_object);

//optimize the memory
if(diff - sizeof(struct slab_chunk) >= sizeof(struct slab_object) + size) {
diff -= sizeof(struct slab_chunk);
*chunks += 1;

while(diff >= (int)(sizeof(struct slab_object) + size)) {
diff -= sizeof(struct slab_object) + size;
*objs += 1;
}
}
}

Danke.

Gruss,
rizor
« Letzte Änderung: 14. May 2011, 09:28 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 14. May 2011, 10:45 »
Benutzt du einen eigenen Bootloader? Dass mehr Code zu undefinierbarem Spinnen führt, hat immer mal wieder was damit zu tun, dass der Kernel schon kaputt im Speicher landet. Eine andere Möglichkeit wäre, dass du irgendwelchen Speicher überschreibst und bei einem kleinen Kernel nichts wichtiges trifft, aber bei einem größeren schon.

Oder ist es eine definierte Art von spinnen, d.h. liefert einfach nur dein Allocator Mist zurück? Wenn ja, was für eine Art von Mist?
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: 14. May 2011, 13:04 »
Nee, ich verwende Grub.
An sich duerfte da nichts passieren.
Mein Boot-Code liegt an der 1MB-Grenze und der Rest (inkl. der Datenstrukturen) liegt an der 3 GB-Grenze. Den Speicher, auf dem ich schreibe, ist der garantiert freie Speicher unterhalb von einem MB (0x8000 -> 0x7ffff). Der Speicher reciht auch, da ich fuer diesen Speicher einen eigenen Manager habe, der den Speicher auch ordentlich verwaltet.
Das komische Verhalten zeigt sich dadurch, dass der GDB sagt, dass ich immer wieder der gleiche Befehl ausgefuehrt wird. Die Funktionen werden zum Teil auch falsch aufgerufen (falsche Parameter).
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 14. May 2011, 18:43 »
So, habe die Funktion mal ungeschrieben, da sie zum Teil falsche Ergebnisse geliefert hat und nun funktioniert der Code, sobald ich ihn in einem Image und mit Qemu -fda ... aufrufe.
Aber wenn ich meinen Kernel mit Qemu -kernel ... aufrufe, wird nicht eine meiner Funktionen (nicht mal _start) angesprungen. Was macht Qemu fuer Unterschiede zwischen -kernel und -fda?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 15. May 2011, 12:48 »
Der Unterschied ist der Bootloader. Mit -fda hast du den GRUB vom Diskettenimage, mit -kernel eben qemu.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 15. May 2011, 14:35 »
Also muesste es ein Bug in qemu sein, oder?
Oder was koennte an meinem Kernel falsch sein, dass qemu den Dienst verweigert und GRUB alles richtig macht?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 15. May 2011, 15:36 »
Vielleicht interpretieren GRUB und Qemu die Multibootspezifikation leicht unterschiedlich und dein Kernel verlässt sich auf ein Verhalten, was Qemu eben nicht hat...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 15. May 2011, 17:13 »
Ohne den Kernel zu kennen, kann man da auch nicht viel dazu sagen. Ich brauch endlich mal einen Debugger mit gescheiter Kristallkugelunterstützung.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 15. May 2011, 17:47 »
Das Problem ist, dass ich nicht genau weiss, wovon das abhaengt, da mein Kernel unter qemu nicht mal aufgerufen wird. Also kann ich auch nicht wirklich sagen wo es haengt
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 16. May 2011, 09:46 »
Du könntest beispielsweise deine Kernelbinary irgendwo hochladen, damit man sich das anschauen kann.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 16. May 2011, 14:20 »
Hallo,


@rizor:
Sicher das Dein Kernel wirklich gar nicht angesprungen wird?
Ich könnte mir ja vorstellen das die unterschiedlichen Loader z.B. die GDT minimal unterschiedlich bauen und deswegen Dein Code beim ersten Speicherzugriff schon im Tripple-Fault landet o.ä., aber das Dein Kernel nichtmal angesprungen wird ohne das der Loader eine Fehlermeldung abgibt erscheint mir doch etwas suspekt.


Ich brauch endlich mal einen Debugger mit gescheiter Kristallkugelunterstützung.
Wenn Du dafür einen preiswerten Lieferanten auftreiben kannst und bereit bist eine Sammelbestellung zu organisieren dann möchte ich schon mal voranmelden das ich auch gerne ein oder zwei Stück hätte. Wichtig wäre mir nur noch die Unterstützung beliebiger CPU-Typen, x86 ist nicht so meine Zielrichtung! ;)


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 16. May 2011, 15:39 »
Wenn mein Kernel in einen Triple-Fault springen würde, dann würde Qemu ja aussteigen mit dem Letzten CPU-Dump, das tut es aber nicht.
Es Steht einfach die Meldung über das SeaBIOS da und sonst passiert nichts.
Wenn ich dem GDB sage, dass er den Code bei _start unterbrechen soll, kommt auch nichts.
Außerdem müsste das mit der GDT doch immer auffallen, oder?
Mein erster Code wird ja noch ganz normal im Lowmem-Bereich ausgeführt. Erst nachdem Paging aktiviert wurde, wird der Kernel im Highmem-Bereich ausgeführt.

@taljeth:
Falls das Problem nach meinen Änderungen immer noch besteht, werde ich es machen.
« Letzte Änderung: 16. May 2011, 15:41 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 16. May 2011, 17:18 »
Mein erster Code wird ja noch ganz normal im Lowmem-Bereich ausgeführt. Erst nachdem Paging aktiviert wurde, wird der Kernel im Highmem-Bereich ausgeführt.

Ich glaube Qemu kann sich an sowas verschlucken, wenn du das im Linkerskript mit AT implementiert hast. Der Multiboot-Loader interpretiert wimre nicht die Felder für die physische Adresse.
« Letzte Änderung: 16. May 2011, 17:38 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 16. May 2011, 17:38 »
Was ist denn AT?
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 16. May 2011, 17:47 »
Wenn du das nicht weißt, hast du vermutlich das Problem nicht. ;)

Mit AT gibt man im Linkerskript die Ladeadresse für eine Sektion an. Damit kann man den Kernel in den hohen Speicherbereich mappen, aber trotzdem mit GRUB an eine niedrige Adresse laden. In vielen Tutorials wird der Kernel ja an die Adresse 0x100000 gelinkt, und muss von GRUB auch dahingeladen werden. Wenn man AT einsetzt, wird GRUB ihn weiterhin an diese Adresse laden, aber gelinkt wird der Kernel an eine andere Adresse (z.B. 0xC0000000).

Ein Beispiel, das das mit einer GDT kombiniert, um von Anfang an unmodifizierte C-Funktionen benutzen zu können, ist hier: http://wiki.osdev.org/Higher_Half_With_GDT
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 16. May 2011, 18:18 »
Wenn ich dich richtig verstanden habe, wird der Code gegen 0xc0000000 gelinkt, aber an 0x100000 geladen, oder?
Das mache ich auch so. Wusste nur nicht, dass man das AT nennt.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 16. May 2011, 18:21 »
Ja, das meine ich.

Das mit dem AT hab ich nicht gut erklärt. Das ist einfach nur das Schlüsselwort dafür, kein Begriff für das Prinzip. Siehe auch http://sourceware.org/binutils/docs-2.17/ld/Output-Section-LMA.html#Output-Section-LMA
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 16. May 2011, 19:00 »
Aber wieso klappt das manchmal und dann wieder nicht?
Ich habe den Code mal ein wenig umgeschrieben und nun funktioniert es einwandfrei.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

 

Einloggen