Autor Thema: "rep outsw" zu schnell?  (Gelesen 4828 mal)

Juggl3r

  • Beiträge: 2
    • Profil anzeigen
Gespeichert
« am: 05. September 2011, 01:27 »
Hallo,

für eine kommende Lehrveranstaltung an unserer Universität soll ich mich ins Thema "Programmieren von OS" einarbeiten. Habe jetzt auch schon einige Tutorials durch und auch schon in einige Projekte eingelesen (Potatoes, prettyOS, geekOS, pintOS, usw.)
Die Wahl des OS wird wahrscheinlich auf Potatoes fallen (in Ansi C geschrieben, Doku für doxygen, nicht allzu "kompliziert und groß", ...)

Nun habe ich aber das Problem, dass auf meinem StandPC Potatoes beim Booten hängen bleibt.
Hier einmal der Link zu Potatoes: http://potatoes-project.tk/

Wenn ich auf meinem StandPC Potatoes starte (auch, wenn ich die fertige .img Dateien downloade und starte), bleibt er bei "Creating FS" hängen.
Habe das ganze einmal debuggt und bin auf folgenden Fehlerverlauf gestoßen:

create_fs() => init_bmap() => mark_block() => wrt_block() => hd_write_sector() => repoutsw()


Repoutsw ist eine in Assembler (in der Datei src\kernel\io\utils.s) geschrieben Funktion:

repoutsw:
cld
mov ecx, [esp+12] ;value
mov esi, [esp+8] ;source buffer
mov edx, [esp+4] ;dest address
rep outsw
ret

An dieser Stelle "hängt" sich das OS auf. Also er macht an dieser Stelle nicht weiter.
Beim Aufruf der Funktion, wird in der ersten Zeile in ECX 256 geschrieben, weshalb "rep outsw" 256 mal wiederholt wird. Schreibe ich z.b. mit mov ecx, 5 den Wert 5 in das Register, hängt er sich nicht auf. Erst wenn der Wert > 7 wird, hängt er sich auf.

Woran kann das liegen? Kann die Anweisung zu schnell sein? Ich habe auch schon versucht das ganze mit jump-to-label Anweisungen abzuändern und "nop"-code einzufügen, um den IO-Ports mehr Zeit zu geben, nur es hat nicht funktioniert.
Das gleiche Probleme habe ich bei der Anweisung rep insw.

Das Problem habe ich auch schon in osdev.org gepostet, dort konnte aber niemand den wirklichen Fehlergrund finden, deshalb hoffe ich, dass vielleicht hier mir jemanden helfen kann.

Mein StandPC ist ein Dualcore x86, auf dem funktioniert es nicht. Auf meinem Laptop (singlecore x86) funktioniert es. Eine andere Testperson (Ubuntu 11.04 (amd64) Prozessor ist ein Intel Core i7 Q720. ) konnte das OS auch ohne Probleme starten.

Wäre euch sehr dankbar, wenn Ihr mir da helfen könntet. Das OS kann sonst nur sehr schwer verwendet werden, wenn dann z.B.: bei der Hälfte der Studenten der Fehler auftritt und wir nicht wissen, woher er kommt. Und selbst weiß ich leider auch nicht mehr weiter.

lg

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 05. September 2011, 11:23 »
Klingt seltsam. Kannst du das Problem auf irgendeinem Emulator reproduzieren? Wenn ja, dann wäre das schonmal ein hilfreicher Ansatz für Debugging.

Bist du dir sicher, dass er im rep outsw hängt? Oder könnte es zum Beispiel passieren, dass nur das ret ins Nichts springt oder ähnliches? Wie hast du denn getestet, wo der Fehler herkommt?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Juggl3r

  • Beiträge: 2
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 05. September 2011, 17:18 »
Also ich habe das ganze unter Ubuntu mit Qemu getestet (Bochs funktioniert irgendwie nicht und bei virtualBox hats Probleme gegeben, weil hda keine .img Datei sein kann und wenn ich das konvertiert habe, er einen Fehler rausgeschmissen hat). Werd jetzt aber mal unter Windows VirtualBox installieren und mit dem Development-Image von meinem Laptop das gleiche auf meinem PC testen, dann seh ich ja, obs die Hardware ist....

Naja, ganz sicher bin ich nicht, dass es genau "rep outsw" ist. Habe immer printf Anweisungen eingefügt und geschaut, wieweit ich komme und aus der Funktion komme ich nicht mehr zurück. Und da mein Assembler eher mager ist und ich nicht weiß, wie ich das weiter Debuggen soll (kann ja auch kein gdb benutzen...) würd ich auf rep outsw tippen.

Rep wird ja ECX mal wiederholt.... Wenn ich die erste Anweisung mit einem "mov ecx, 5" ersetze, dann hängt er sich nicht auf. Nur wenn in ECX was größeres steht, z.b. 20. Wenn ich z.B.: 7 hineinschreibe, dann hängt er sich beim ersten Funktionsaufruf von der Routine nicht auf. Allerdings später beim 5ten oder 6ten mal (wo immer noch ecx mit 7 befüllt wird).
Wie gesagt, sehr, sehr komisch.

Es könnte auch sein, dass wenn ecx zu groß ist, der Speicherbereich, der geschrieben wird, in den Stack hineinragt und die return Adress überschreibt, das halte ich aber eher für sehr unwahrscheinlich..... Vorallem auch, weil bei einer ähnlichen Funktion mit rep insw das gleiche Problem auftritt und da nichts überschrieben wird....

Jemand eine Idee, wie ich das zumindest debuggen könnte? ODer was ich als nächstes machen könnte?

Kann es sein, dass es damit zu tun hat, dass alles mit CHS Modus auf die HD geschrieben wird? (also gibt es HD's, bei denen CHS nicht mehr funktioniert?) Hab mein Problem bei uns im Universitätsforum gepostet und ein paar Leute es austesten lassen, bei vielen mit besseren Prozessoren funktioniert es trotzdem.
Deshalb glaub ich nicht so an das Argument "rep outsw" ist zu schnell.....

Mir fällt aber nichts mehr ein, wie ich das weiter untersuchen könnte oder was die nächsten Schritte wären.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 05. September 2011, 20:57 »
Hallo,


dieses Problem klingt für mich sehr merkwürdig. Grundsätzlich ist es zwar theoretisch denkbar das die I/O-Befehle zu schnell kommen aber dass das in den letzten 20 Jahren tatsächlich mal zu einem Problem geworden ist wäre mir neu. I/O-Befehle werden von allen x86-CPUS der letzten 20 Jahre streng Seriell und ohne jegliche Instruktion-Level-Parallelität ausgeführt (so ein I/O-Befehl könnte ja das A20-Gate oder ein EMS-Steuerregister beeinflussen und das muss noch vor der Ausführung des nächsten Befehls wirksam werden können, also so lange der I/O-Befehl nicht komplett comitted wurde wird der nächste Befehle noch nicht einmal in die Prefetch-Stufe geladen bzw. diese solange als leer blockiert). Das REP-Präfix kann an diesem Verhalten aber einiges optimieren, zumindest für die wiederholten I/O-Befehle. Die einzelnen I/O-Zugriffe werden auch immer einzeln nach draußen gereicht (es gibt bei I/O kein Read-Prefetch und kein Write-Combining), selbst bei der REP-Version.

Was ich mir aber Vorstellen kann ist das die einzelnen I/O-Aktionen mit einem zu geringen Abstand untereinander kommen. Ich würde vorschlagen einfach mal eine simple Zeit-Vertrödel-Schleife wie die    pushad
    mov     ecx,1234    ;den nachfolgenden Code X-mal wiederholen
lloop:
    xor     eax,eax
    cpuid               ;der Befehl serialisiert die CPU-Pipeline
    pause               ;CPU kurz schlafen lassen (damit unser CO2-Gewissen sauber bleibt)
    loop    lloop
    popad
davor zu packen, einfach damit die HW-Komponente etwas mehr Zeit hat sich vorzubereiten (mit dem Wert für ECX ruhig ein wenig spielen bis es zuverlässig(er) funktioniert).


Mehr kann ich so aus dem Bauch heraus auch nicht orakeln, es wäre auf jeden Fall sehr hilfreich mal den genauen Kontext und die konkret benutzte Hardware-Komponente zu kennen. In Emulatoren sollten solche Phänomene grundsätzlich nicht auftreten, wenn der Code in verschiedenen Emulatoren zuverlässig funktioniert ist das IMHO ein gutes Zeichen dafür das die Probleme auf der realen HW tatsächlich mit dem Timing zu tun haben.


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

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 05. September 2011, 21:59 »
Also ich habe das ganze unter Ubuntu mit Qemu getestet
Und mit welchem Ergebnis? ;)

Falls du dort auch einen Hänger bekommst, dann würde ich tatsächlich damit weitermachen, die hängende VM mal anzuhalten und im qemu-Monitor bzw. mit gdb näher nachzuschauen, was da eigentlich los ist.

Wenn du nur richtige PCs hast, kannst du mal probieren, nach dem rep outsb und vor dem ret irgendwas zu machen, das sehr eindeutig erkennbar ist. Ein ud2 zum Beispiel und falls er tatsächlich dort hinkommt, hoffen, dass dein Exceptionhandler einen nützlichen CPU-Dump zustandebringt.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen