Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - OsDevNewbie

Seiten: [1] 2 3 ... 15
1
Softwareentwicklung / Binutils LD 2.36.1
« am: 14. April 2021, 02:30 »
Hallo zusammen.

Ich habe bis jetzt zuverlässig den binutils ld mit version 2.26 verwendet. Ich dachte mir aber es wird mal Zeit für ein Update auf Version 2.36.1 (die zum jetzigen Zeitpunkt aktuellste Version). Das erstellen des ELF-Linkers und des Cross-Linkers hat auch relativ gut funktioniert. Nur habe ich jetzt Problem, dass beim Linken der Programme für mein OS ich folgende Fehlermeldung bekomme:
~/YourOS/crosstools/env/lib/gcc/x86_64-pc-youros/7.5.0/../../../../x86_64-pc-youros/bin/ld: failed to convert GOTPCREL relocation; relink with --no-relax
Nun ist noch anzumerken, dass ich die Programme an die 512GiB-Grenze (0x8000000000) linke. Das hat bisher gut funktioniert (man muss halt mit -fpic kompilieren). Nur mit dem neuen Linker klappt das nicht mehr. Das passiert auch, wenn ich die selben Objekt-Dateien nehme wie für den 2.26 Linker.

Ich habe dann mal ausprobiert was die Fehlermeldung auch vorschlägt. Also `-Wl,--no-relax` zum Makefile hinzugefügt und siehe da es funktioniert. Nur ich würde gerne Verstehen, warum es ohne dieses Flag nicht funktioniert.

Nach ein paar Nachforschungen habe ich rausgefunden, dass diese Fehlermeldung erscheint bei einem Overflow, da die relative Addressierung in x64 ja trotzdem 32-bit signed ist. Aber der 2.26 Linker hat ja damit auch kein Problem und das Binary ist nur ein paar KB gross.

Weiss jemand von euch was das Problem sein könnte?
2
Das Wiki / Re: PHP Warnungen
« am: 08. April 2017, 16:11 »
Danke.
3
Das Wiki / PHP Warnungen
« am: 05. April 2017, 17:41 »
Hallo,
als ich heute auf dem Lowlevel-Wiki auf die Dateisystem-Seite gehen wollte wurde ich mit einer PHP-Warnungsmeldung empfangen. Das einzigste, was von der eigentlichen Seite geladen wird ist das Logo. Ich der Server-Administrator sollte sich das mal anschauen.
Ich wollte das hier nur mal mitteilen.
4
Softwareentwicklung / Re: Makefile geteilter Source Code
« am: 04. April 2017, 11:03 »
Ok danke für deine Antwort.

Wie gesagt, das einzige was sich ändert ist halt, dass bei der normalen libc Syscalls verwendet werden und bei der "kernellib" halt direkt die Funktion, die ansonsten vom Syscall aufgerufen wird. Ich finde das kein gutes Software Engineering, wenn man den genau gleichen Code mehrmals in verschiedenen Dateien hat.
5
Softwareentwicklung / Re: Makefile geteilter Source Code
« am: 03. April 2017, 14:12 »
Das Problem ist, dass im C-Code je nach Target, also Kernel oder libc, verschiedene Funktionen aufgerufen werden müssen (z.B. im Kernel die Funktion zum Öffnen einer Datei, wobei in der libc den entsprechenden Syscall). Dazu definiere ich bei einem Kernel-Build ein Macro (BUILD_KERNEL). Also muss ich den Source Code der Libc doppelt kompilieren. Ist das auch möglich mit Make?
6
Softwareentwicklung / Makefile geteilter Source Code
« am: 02. April 2017, 22:55 »
Hallo zusammen.
Ich verwende seitdem ich angefangen habe meinen Kernel zu Programmieren Eclipse, das für mich automatisch die Makefiles erzeugt und dann alles kompiliert. Ich möchte jetzt umsteigen auf ein eigenes Makefile. Das kann man ja dann in Eclipse verwenden um den Code zu kompilieren. Der Grund für den Umstieg ist, dass man den Kernel auch oihne Eclipse kompilieren können soll.
Das Problem, das ich jetzt aber habe ist, dass ich grosse Teile meiner Standard C Library auch im Kernel verwende (z.B. die Heapverwaltung, printf, usw.). D.h. das Makefile muss den Kernel und die Library kompilieren und dafür entsprechende Macros an den Compiler übergeben. Nur wie geht das in einem Makefile? Geht das überhaupt?
Also das Ziel ist, dass make all das Kernelbinary und die Library erstellt.
Es wäre schön, wenn ich Make verwenden könnte, denn ich denke es ist einfacher zu portieren als CMake oder?
7
Softwareentwicklung / Re: Quadratwurzel schnell berechnen
« am: 01. March 2017, 14:12 »
Hast du gemessen oder geschätzt?
Ich habe im Intel optimization manual nachgeschaut. Dort sind aber leider nur die Latenzen auf Prozessoren der letzten paar Generationen verfügbar.

Hast du da auch den Code dazu?
Wäre sehr interessant. :-)
Ich habe im Anhang ein C Programm (unkommentiert, aber hoffentlich leicht lesbar), dass auf verschiedene Arten die Wurzel aus einer int Zahl zieht. Bei meiner Testmaschine (i7-4770k mit 32GiB RAM) kommen folgende Ergebnisse raus:
Alloziere 3000000000 (11718750.00 KiB) Elemente...OK
Initialisiere...OK
Berechne (calc_sqrt_float_sse)...OK(1.642945 Zyklen/Element)
OK
Berechne (calc_sqrt_float_avx)...OK(1.619843 Zyklen/Element)
OK
Berechne (calc_sqrt_double_sse)...OK(6.353434 Zyklen/Element)
OK
Berechne (calc_sqrt_double_avx)...OK(6.327483 Zyklen/Element)
OK
Berechne (calc_sqrt_float_sse_2x)...OK(1.621323 Zyklen/Element)
OK
Berechne (calc_sqrt_float_avx_2x)...OK(1.625151 Zyklen/Element)
OK
Berechne (calc_sqrt_double_sse_2x)...OK(6.315364 Zyklen/Element)
OK
Berechne (calc_sqrt_double_avx_2x)...OK(6.325675 Zyklen/Element)
Wie du siehst ist es sehr schnell. (Damit die AVX-Funktionen ausgeführt werden musst du beim Compilieren AVX aktivieren).
(Wieso die AVX-Variante gleich schnell ist wie die SSE-Variante verstehe ich selber noch nicht ganz.)
Wenn man die Wurzel aus floats zieht, dann hat man eine Genauigkeit von 24-Bit ich weiss nicht ob dir das reicht. Deshalb hab ich noch die double Varianten davon gemacht, da hat man eine höhere Genauigkeit (wie hoch steht nicht im Manual), aber sind teilweise ein bisschen langsamer.
Du kannst das Programm ja mal bei dir testen und schauen, ob es schnell genug ist für dich.
Du darfst auch von meinem Code kopieren oder mir sagen, wenn ich etwas gemacht habe.

Ich muss noch dazu sagen, dass ich jetzt die Umwandlung zwischen ints und floats in meinen Berechnungen in meinem Post nicht einberechnet habe (die kosten immer so 4 Zyklen pro umwandlung), sie werden aber im Programm mit eingerechnet.
8
Softwareentwicklung / Re: Quadratwurzel schnell berechnen
« am: 25. February 2017, 23:12 »
Du könntest die x86-Instruktion "sqrtss" verwenden. Sie berechnet eine Quadratwurzel aus einer 32-bit Floating-Point-Zahl und braucht so 13 Zyklen auf modernen Prozessoren. Mit "sqrtps" kannst du sogar 4 Zahlen gleichzeitig berechnen in der gleichen Zeit. Das führt dazu, dass du 13/4 = 3.25, also etwa 4 Zyklen pro Zahl brauchst. Natürlich geht das nur, wenn du SSE verwenden kannst.
9
Lowlevel-Coding / Re: Syscall wird nicht aufgerufen
« am: 21. September 2016, 09:18 »
bl ist das erste Byte im ebx-Register. Es wird nur dieses befüllt, weil '0' nur 1 Byte entspricht und somit '0'+x auch nur ein Byte belegt. Daher wäre es nicht falsch anzunehmen, dass der Compiler nur das bl-Register beschreibt. Durch das beschreiben, des bl-Registers wird der Inhalt des restlichen Register aber nicht gelöscht und deshalb kann dort noch "Abfall" enthalten sein.
10
Softwareentwicklung / Re: GNU ld
« am: 02. September 2016, 18:18 »
Wie siehts aus wenn du anstatt "ld -T kernel.ld" "ld --script=kernel.ld" verwendest?
11
Das Wiki / Re: Das Wiki und https
« am: 25. May 2016, 15:06 »
Letsencrypt bietet ein Script an welches alles für dich erledigt. Also praktisch Plug-n-Play :-D.
12
Interrupthandler, die mit cli anfangen, sind kaputt. Aber ich nehme an, er regelt das über den Deskriptortyp (Trap Gate oder Interrupt Gate) in der IDT, und das ist völlig in Ordnung.
Das ist so korrekt.
Deshalb verstehe ich auch nicht wieso keine Interrupts ausgelöst werden während des Syscalls. Und es werden ja auch keine Interrupts ausgelöst wenn man über den syscall-Befehl die Syscalls ausführt.
13
Wenn du in den Syscall-Implementierungen globalen Zustand benutzt, brauchst du Locking, weil du nicht weißt, an welcher Stelle der Syscall von einem anderen Task unterbrochen werden könnte, der den globalen Zustand ebenfalls liest oder sogar ändert.
Das ist korrekt. Da muss man echt aufpassen.

Ich dachte, du willst einfach nur Zeit messen? Dafür ist RDTSC auf den meisten CPUs ziemlich gut geeignet.
OK, da hast du natürlich recht.

Aber leider löst das mein ursprüngliches Problem nicht.
14
Innerhalb von Interrupthandlern sind Interrupts normalerweise gesperrt, das sollte auch für Software-Interrupts gelten.
Also bei meinem Kernel deaktivieren alle Interrupts Interrupts ausser der Interrupt, der für Syscalls verwendet wird.

Das macht einen Kernel sehr viel einfacher.
Wieso macht das den Kernel einfacher? Ich habe mir Syscalls als einen Funktionsaufruf einer Funktion im Kernel vorgestellt. Und bei einem Interrupt wird der aktuelle Status einfach wie jeder andere gesichert (ausser, dass der Stack weiterverwendet wird). Das hat bis jetzt auch gut funktioniert.
Früher hatte ich einen Bug, wobei der Zustand nicht richtig wiederhergestellt wurde, wenn ein Interrupt ausgelöst wurde während man einen Syscall ausführte, dadurch weiss ich, dass (zumindest damals) Interrupts ausgelöst werden.
Wenn ich mir das rflags-Register im Debugger (Bochs) während der Ausführung eines Syscalls anschaue, sind die Interrupts, sowohl wenn man den Syscall über die syscall-Instruction oder über Interrupts ausführt, aktiviert.

Dazu muss der Handler seine eigene Interruptquelle abschalten (sonst führt ein zu schnell feuernder Interrupt zu einem Stack-Overflow) und kann dann Interrupts im Handler wieder einschalten (sti). Außerdem müssen dann alle Funktionen, die von mehreren Interrupts aus aufgerufen werden können, reentrant sein.
Das kann nicht passieren, da eben alle Interrupts (ausser der Syscall Interrupt) Interrupts deaktivieren.

Statt die Zeit über einen Tick-Timer zu messen, würde ich allerdings zu RDTSC o.ä. raten, das ist für sowas gemacht.
RDTSC gibt einen Zähler zurück, welcher mit einer nicht weiter definierten Taktrate incrementiert wird. Diese ist aber nicht gleich der Anzahl Takte, die bisher vergangen sind, da sich der Takt an die entsprechenden Verhältnisse anpasst, aber der Takt mit der der Zähler hochgezählt wird bleibt gleich.

Trotzdem Danke für deine Antwort.
15
Softwareentwicklung / Interrupts durch Syscalls blockiert
« am: 05. May 2016, 20:46 »
Hallo zusammen,

Ich wollte den Performanceunterschied zwischen den Assembler-Instructionen "int" (im Folgenden als Interrupt bezeichet) und "syscall" (im Folgenden als Syscall bezeichet) messen. Dazu habe ich eine Schleife gemacht, die 100'000'000 mal durchlaufen wird. Einmal wird dann ein Interrupt ausgelöst und das andere Mal wird ein Syscall ausgeführt. Vor und nach der Schleife speichere ich die aktuelle Laufzeit des ganzen System ab und gib am Schluss die Differenz der beiden Werte aus, also die gesamte Zeit, die die Schleife benötigt hat. Die Uptime wird vom Handler, der die Interrupts vom PIT handelt, incrementiert. Der PIT löst jede Millisekunde einen Interrupt aus. Das funktioniert soweit sehr gut. In meiner Shell kann man die aktuelle Uptime ausgeben lassen und die stimmt.

Jetzt ist das Problem, dass die Anfangszeit der Schleife immer gleich ist wie die Endzeit, was dazu führt, dass 0ms ausgegeben wird, was nicht stimmen kann, da es schon ein paar Sekunden dauert bis die Schleife beendet ist. Nach ein bisschen Debuggen ist mir aufgefallen, dass während der Schleife keine Timer-Interrupts mehr ausgelöst werden und dadurch wird auch Uptime nicht mehr incrementiert.

Nach der Schleife wird Uptime wieder incrementiert. Dieses Verhalten habe ich sowohl mit Interrupts als auch mit Syscalls.
In den Syscalls und im entsprechenden Interrupt werden Interrupts nicht deaktiviert, also sollte Uptime hoch gezählt werden, was anscheinend nicht der Fall ist.

Wieso gibt es einen "Unterbruch" der Timer-Interrupts? Sind das zu viele Interrupts für die CPU? Aber wieso passiert das dann auch bei Syscall?

Hier die entsprechende Funktion:
static void perftest()
{
size_t i, count;
SIS start, end;
uint64_t time;
printf("Starting performance test:\n");

getSysInfo(&start);
for(i = 0; i < 100000000; i++)
{
asm volatile("int $48": "=a"(count): "D"(61));
}
getSysInfo(&end);
asm volatile("int $48":: "D"(62));
time = end.Uptime - start.Uptime;
printf("Interrupts: %zu in %lums => %f/s\n", count, time, count / (double)(time?:1000.0) * 1000);

getSysInfo(&start);
for(i = 0; i < 100000000; i++)
{
asm volatile("mov %1,%%rdi;syscall": "=a"(count): "i"(61): "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11");
}
getSysInfo(&end);
asm volatile("mov %0,%%rdi;syscall":: "i"(62): "rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11");
time = end.Uptime - start.Uptime;
printf("Syscalls: %zu in %lums => %f/s\n", count, time, count / (double)(time?:1000.0) * 1000);

printf("End of performance test\n");
}
getSysInfo() ist die Funktion die mir die Uptime (und noch andere Infos) zurückgibt.

Hier die entsprechenden Funktionen, die durch Interrupts oder durch Syscalls aufgerufen werden (Funktionsnummer steht im rdi-Register):

static uint64_t count = 0;
static uint64_t perfTest() //Funktion 61
{
return ++count;
}

static void resetPerfTest() //Funktion 62
{
count = 0;
}

Das ganze läuft in meiner Shell im Userspace.

Ich hoffe ihr könnt mir helfen.
Ansonsten wünsche ich euch noch einen schönen Abend.
16
Das Wiki / Re: Das Wiki und https
« am: 24. January 2016, 00:12 »
Hey,
zahlst du etwas für das Zertifikat? Schau dir sonst mal Let's Encrypt an.
17
Das Wiki / Re: Das Wiki und https
« am: 23. January 2016, 19:14 »
Ist mir auch schon aufgefallen. Wollte ich auch schon melden kam aber nicht dazu.
18
Lowlevel-Coding / Re: anfängerfrage: problem mit tutorial
« am: 21. January 2016, 15:47 »
Ich benutze im Übrigen eine Ubuntu vm um das ganze zu programmieren, und ich habe noch keine Probleme mit dem kleinen .s. Warum würde das denn zu Problemen kommen? Gibt es da build tools die die entsprechende .S Endung voraussetzen?

Also eine .S-Endung bedeuted, dass dies eine Assemblerdatei, die noch durch den Präprozessiert werden muss. Als Ergebnis entsteht dann eine .s Assemblerdatei und diese wird dann direkt assembliert.
So hab ich das auf jeden Fall mal gelernt. Kann natürlich auch falsch sein. Schau einfach mal das Ergebnis mit objdump an, dann siehst du, ob deine Datei richtig assembliert wurde.
19
Ich habe es jetzt mal verglichen mit der Asugabe von lspci und da ist mir dann aufgefallen, dass mein Code immer nur die Funktion 0 des Gerätes prüft. Nach dem Fix erkennt es jetzt den onboard SATA Controller und findet somit auch meine SSD und HDD, die daran angeschlossen sind.
Prüfst du auch ordentlich, ob es überhaupt ein Multifunktionsgerät ist, bevor du die Funktionen prüfst, oder gehst du immer alle Funktionen durch?
Ja, ich überprüfe das oberste Bit des Header-Typs mit
if(header & 0x80){...} //Teste die anderen Funktionen

Zitat
Aber mal ne Frage zum CDI ATA-Treiber: Wie wäre es eigentlich, wenn man dort die Unterstützung von mehreren Controller einbaut, denn auf meinem anderen Test-PC habe ich zwei ATA-Controller aber nur der erste wird erkannt => es wird nur das CDROM-Laufwerk erkannt aber nicht die Festplatte, die sich am zweiten Controller befindet. Die Controller sind getrennt auf dem PCI-Bus.
Ich bin mir sicher, dass niemand etwas dagegen hat, den Code ins CDI-Repository zu übernehmen, wenn du den Treiber entsprechend erweiterst. Ich denke, man muss ein kleines bisschen aufpassen, dass man reine ISA-Controller nicht kaputtmacht (falls irgendjemand noch sowas hat...) und der erste Controller auch nicht doppelt auftaucht, aber an sich sollte die Erweiterung nicht schwer sein.
Mal schauen was ich da tun kann.
Was meinst du denn mit "reine ISA-Controller"? Wenn man die so kaputt macht, dann wäre das doch auch ein Problem mit der aktuellen Methode.

Vielen Dank für Eure bisherigen Antworten.
20
Ich habe es jetzt mal verglichen mit der Asugabe von lspci und da ist mir dann aufgefallen, dass mein Code immer nur die Funktion 0 des Gerätes prüft. Nach dem Fix erkennt es jetzt den onboard SATA Controller und findet somit auch meine SSD und HDD, die daran angeschlossen sind.

Aber mal ne Frage zum CDI ATA-Treiber: Wie wäre es eigentlich, wenn man dort die Unterstützung von mehreren Controller einbaut, denn auf meinem anderen Test-PC habe ich zwei ATA-Controller aber nur der erste wird erkannt => es wird nur das CDROM-Laufwerk erkannt aber nicht die Festplatte, die sich am zweiten Controller befindet. Die Controller sind getrennt auf dem PCI-Bus.
Seiten: [1] 2 3 ... 15

Einloggen