Lowlevel

Lowlevel => OS-Design => Thema gestartet von: Svenska am 06. November 2010, 17:40

Titel: Adressraum für Kernel und Prozesse
Beitrag von: Svenska am 06. November 2010, 17:40
Hallo,

die Frage lautet und ergab sich aus der Diskussion mit FlashBurn an anderer Stelle:

Warum liegt der Kernel üblicherweise im virtuellem Adressraum eines jeden Prozesses?


Meinst du das du den Funktions-Code von einer Kernel-Funktion in den UserSpace mappst und dort dann vom "User" der Code ausgeführt werden kann?
Nicht wirklich... allerdings hab ich keine Ahnung, was ich meine.

Der Prozess fordert einen ausgerichteten Buffer vom Kernel an und merkt sich dessen Zeiger. Dann füllt er diesen mit Daten, setzt die Register (Funktionsnummer, Zeiger auf Buffer, Buffergröße) und ruft dann einen Syscall auf (z.B. "int 80h"). Kann der Kernel dann mit diesem Zeiger etwas anfangen, also den entsprechenden Bereich in seinen eigenen Adressraum mappen und verarbeiten?

Gruß,
Svenska
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 06. November 2010, 18:01
Zitat von: svenska
Warum liegt der Kernel üblicherweise im virtuellem Adressraum eines jeden Prozesses?
Performance! Und bei einer 64bit Architektur musst du den Kernel auch nicht in einen anderen Adressraum packen, da du ja genug hast.

Zitat von: svenska
Der Prozess fordert einen ausgerichteten Buffer vom Kernel an und merkt sich dessen Zeiger. Dann füllt er diesen mit Daten, setzt die Register (Funktionsnummer, Zeiger auf Buffer, Buffergröße) und ruft dann einen Syscall auf (z.B. "int 80h"). Kann der Kernel dann mit diesem Zeiger etwas anfangen, also den entsprechenden Bereich in seinen eigenen Adressraum mappen und verarbeiten?
Frage wäre was dir das bringen soll, ob du die Daten nun über den Stack oder über einen solchen Buffer (der mehr Speicher verbraucht als wenn man das alles übern Stack macht) an den Kernel weitergibst sollte fast egal sein.

Bzw. die Idee an sich gefällt mir (pro Thread ein 4KB Buffer für Syscalls, aber das wäre halt eigentlich nen tierischer Overhead, denn wieviel Speicher wird man wohl max pro Syscall brauchen, 128Byte?), aber warum willst du diesen Buffer auch im KernelSpace nochmal mappen? Du kannst doch vom KernelSpace aus schon auf den UserSpace zugreifen.

Es gibt ein Bsp. wo das wahrscheinlich sogar so gemacht wird. Wimre dann hat bei MacOSX der Kernel seinen eigenes PageDir und ist somit nicht in jeden Prozess gemappt, sondern da ist immer nur ein kleiner Stub, der das PageDir in den Kernel wechselt.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 06. November 2010, 18:11
Warum liegt der Kernel üblicherweise im virtuellem Adressraum eines jeden Prozesses?
Zum einen, wie FlashBurn schon sagte Performance. Ein Kontextwechsel bedeutet auf x86 einen TLB-Flush und der kostet ein bisschen was.

Zum anderen weil ein paar Teile vom Kernel immer gemappt sein müssen, weil der Prozessor sie benutzt. Die GDT, die IDT und das aktive TSS dürften das absolute Minimum sein, ohne das keinen Wechsel in der Userspace (und vor allem zurück) geht. Und wenn man das sowieso machen muss, ist es am geschicktesten, einfach gleich alles zu mappen.

Außerdem hat es auch noch den Vorteil, dass sich Kernel- und Userspaceadressen nicht überschneiden können und damit zwingend in verschiedenen Adressräumen liegen müssen. Der Kernel muss ja immer mal wieder auf Daten des Userspace zugreifen (z.B. für read, write, send_message, ...) und es wäre umständlich, wenn er dazu jedesmal ein temporäres Mapping anlegen müsste.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Svenska am 08. November 2010, 10:23
Hallo,

das heißt, im Adressraum eines jeden Userspace-Programms müssen mindestens GDT, IDT und TSS vorhanden sein?

Wenn ein Userspace-Prozess einen Syscall aufruft und damit in den Kernel springt, kann der Kernel trotzdem ohne weiteres auf die Userspace-Ressourcen zugreifen? Was, wenn sich die Adressräume überschneiden?

Was muss alles im Kernel-Adressraum liegen, zusätzlich zu Code&Daten, aus denen der Kernel besteht? (Mir fallen da konkret der lineare Grafikspeicher und der PCI-Adressraum ein. Was noch?)

Da fehlt mir irgendwie der Überblick.

Gruß,
Svenska
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 08. November 2010, 11:35
Zitat von: svenska
Wenn ein Userspace-Prozess einen Syscall aufruft und damit in den Kernel springt, kann der Kernel trotzdem ohne weiteres auf die Userspace-Ressourcen zugreifen? Was, wenn sich die Adressräume überschneiden?
Ja, der Kernel kann dann einfach per Pointer (auch wenn man das so einfach nicht machen sollte) auf UserSpace Sachen zugreifen und es kann nicht zu Überschneidungen kommen, da der User 3GB und der Kernel 1GB (z.B. unter Linux), von den vorhanden 4GB Adressraum, bekommt.

Zitat von: svenska
Was muss alles im Kernel-Adressraum liegen, zusätzlich zu Code&Daten, aus denen der Kernel besteht? (Mir fallen da konkret der lineare Grafikspeicher und der PCI-Adressraum ein. Was noch?)
Kommt ganz darauf an von was für einem Kernel wir hier sprechen. Ansonsten reicht alles was man für IPC, VMM, PMM, IRQ und halt Task/Thread-Sachen braucht.
Denn Rest kann man ja im UserSpace machen.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Svenska am 08. November 2010, 13:23
Was passiert, wenn der Kernel nicht im letzten GB des RAMs liegt, sondern die Adressräume sich überschneiden? Geht das dann immernoch so einfach oder muss ich dann per Hand ummappen?
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 08. November 2010, 13:34
das heißt, im Adressraum eines jeden Userspace-Programms müssen mindestens GDT, IDT und TSS vorhanden sein?
Du brauchst sinnvolles Interrupthandling, und das braucht im Userspace eben diese drei Dinge (IDT um den Interrupthandler nachzuschlagen, GDT um dessen Codesegment zu laden, TSS für den Kernelstack). Ansonsten kommst du nie wieder in den Kernel zurück.

Zitat
Wenn ein Userspace-Prozess einen Syscall aufruft und damit in den Kernel springt, kann der Kernel trotzdem ohne weiteres auf die Userspace-Ressourcen zugreifen?
Spricht nichts dagegen. In der Praxis wird der Kernel natürlich vorher noch prüfen, ob das tatsächlich Daten sind, auf die der Prozess zugreifen können soll.

Zitat
Was, wenn sich die Adressräume überschneiden?
Dann hast du unseren Ratschlag ignoriert, das bleiben zu lassen, und wirst wohl oder übel den Kontext wechseln müssen. ;)

Zitat
Was muss alles im Kernel-Adressraum liegen, zusätzlich zu Code&Daten, aus denen der Kernel besteht? (Mir fallen da konkret der lineare Grafikspeicher und der PCI-Adressraum ein. Was noch?)
Es gibt nicht nur monolithische Kernel...
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Svenska am 08. November 2010, 16:24
Zitat
Was muss alles im Kernel-Adressraum liegen, zusätzlich zu Code&Daten, aus denen der Kernel besteht? (Mir fallen da konkret der lineare Grafikspeicher und der PCI-Adressraum ein. Was noch?)
Es gibt nicht nur monolithische Kernel...
Also nur Code, Daten und IPC-Schnittstelle bei einem Mikrokernel, und was ich schrieb bei einem Monolithen?
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 08. November 2010, 17:05
Also was verstehst du darunter das sich die Adressräume überschneiden?

Und was würdest du für Vorteile sehen, wenn der Kernel seinen eigenen 4GB Adressraum hat und nicht in jedem Prozess eingeblendet ist?
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Svenska am 08. November 2010, 22:17
Wenn der Kernel im Adressraum von 0 bis 1G liegt und die Anwendungen jeweils von 0 bis 4G-4M liegen, wobei in den letzten 4M die benötigten Strukturen eingeblendet sind, dann überschneiden sich die Adressräume.

Der Vorteil ist, dass du Anwendungen nahezu volle 4 GB virtuellen Speicher zur Verfügung stellen kannst.

Ob das performant und sinnvoll ist, sei mal dahingestellt. Darum die Frage.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 10:30
Zitat von: svenska
Wenn der Kernel im Adressraum von 0 bis 1G liegt und die Anwendungen jeweils von 0 bis 4G-4M liegen, wobei in den letzten 4M die benötigten Strukturen eingeblendet sind, dann überschneiden sich die Adressräume.
Das geht aber nur, wenn der Kernel sein eigenes PageDir bekommt und dann kannst du ihm auch gleich die vollen 4GB geben.
Ansonsten geht es nicht das Kernel und Anwendungen im gleichen Adressraum sind und sich überschneiden.

Zitat von: svenska
Der Vorteil ist, dass du Anwendungen nahezu volle 4 GB virtuellen Speicher zur Verfügung stellen kannst.
Naja, da wäre halt die Lösung das man irgendwo hin die Strukturen packt die auf jeden Fall benötigt werden und nen Stub wie man in den Kernel wechselt.
Dann ist das möglich und sollte auch nicht alzu schwer sein, nur die Performance wird dann halt nicht so berauschend sein bzw. müsstest du dann dein komplettes Konzept auf SharedMem ausrichten und vorallem sind dann auch Thread-Wechsel sehr "teuer".
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 11:10
Um Threadwechsel würde ich mir keine Sorgen machen, das passiert jedenfalls im Vergleich selten genug. Aber Syscalls werden ordentlich teuer.

Statt deinem Stub könntest du übrigens auch auf Hardwaremultitasking umsteigen und die CPU das alles machen lassen.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 11:27
Zitat von: taljeth
Statt deinem Stub könntest du übrigens auch auf Hardwaremultitasking umsteigen und die CPU das alles machen lassen.
Du willst also etwas langsames noch langsamer machen ;)

Zumal das nicht wirklich portabel ist.

Zitat von: taljeth
Um Threadwechsel würde ich mir keine Sorgen machen, das passiert jedenfalls im Vergleich selten genug. Aber Syscalls werden ordentlich teuer.
Das "lustige" ist, es würde nur Sinn machen wenn man nen richtigen mikro MikroKernel so implementiert, weil dann wäre jeder Syscall eigentlich eh ne Nachricht zu versenden und dafür musst du eh das PageDir wechseln, also ist das auch nicht so schlimm. Nur braucht ein solcher MikroKernel auch nicht so viel Speicher das es sich lohnen würde ihn in einen extra Adressraum zu packen.

Was die 4GB für die Apps angeht. Ich denke 3GB sollten wirklich reichen und wenn man mehr braucht, 64bit!
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 11:54
Du willst also etwas langsames noch langsamer machen ;)
Hm, weißt du zufällig, was Hardware-MT so langsam macht? Eventuell gerade, dass der TLB jedesmal geflusht wird? Irgendwas muss ja mehr gemacht werden, damit es langsamer wird. Weiß zufällig jemand Bescheid?

Zitat
Zumal das nicht wirklich portabel ist.
Wir reden hier eh über x86 und teilweise x86-spezifische Probleme. Interrupthandling ist nie portabel.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 12:04
Zitat von: taljeth
Hm, weißt du zufällig, was Hardware-MT so langsam macht?
Wimre, war es "nur" das die Register ja in das TSS kopiert werden. Vorteil vom Software-Multitasking ist das es portabel ist und das du eh schon auf den Stack zugreifst, der also schon mal im TLB/Cache ist und du dann mit nem "pushad" alle Register einfach und schnell gespeichert hast.
Auch hat Intel das Hardware-Tasking dann nicht mehr weiter optimiert, weil es halt kaum bis gar nicht benutzt wurde.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 13:48
Naja, ob die Register jetzt vom Prozessor ins TSS oder von dir auf den Stack gesichert werden, sollte eigentlich keinen großen Unterschied machen. Was den Cache betrifft, dürfte das ganze sowieso ein, zwei Cache Lines für sich brauchen, und ob die dann für den Stack oder das TSS zuständig sind, macht für mich in meiner naiven Herangehensweise keinen sichtbaren Unterschied.

Und was an für x86 implementiertem Software-Multitasking portabel sein soll, musst du mir erst noch erklären. Diese Teile eines OS sind allgemein architekturabhängig, egal welche Technik man jetzt nimmt.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 14:04
Zitat von: taljeth
Und was an für x86 implementiertem Software-Multitasking portabel sein soll, musst du mir erst noch erklären. Diese Teile eines OS sind allgemein architekturabhängig, egal welche Technik man jetzt nimmt.
Ich behaupte mal alle Architekturen haben nen Stack und wenn du also auf allen Architekturen die Register auf dem Stack sicherst, ist das portabel ;)
Schon alleine das Wort "Software"-Multitasking impleziert doch das es portabel ist, weil es in Software und nicht in Hardware gemacht wird.

An einer anderen Stelle hatten wir mal das Bsp. das irgendein BSD die ganze Verschlüsselung im WLAN per Software macht und so jede WLAN-Hardware WPA2 beherrscht und genauso ist das mit Software-Multitasking. Du kannst das auf jeder Architektur umsetzen auch wenn sie das gar nicht in Hardware (das Multitasking) unterstützt.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 14:46
Wenn das so plattformunabhängig ist, dann sichere doch mal auf PPC die Register eax, ebx, ecx, edx, esi, edi usw. weg. ;) Allein dass etwas Software ist, macht es noch nicht portabel. Vor allem, wenn es - wie dieser Code - in Assembler geschrieben ist. Oder wir haben grundlegend unterschiedliche Vorstellungen davon, was das Wort "portabel" aussagt.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 14:56
Zitat von: taljeth
Oder wir haben grundlegend unterschiedliche Vorstellungen davon, was das Wort "portabel" aussagt.
An dem Bsp. heißt für mich portabel das ich den Algo genauso wieder umsetzen kann ohne das ich erst irgendwelche Hardware sachen machen muss, sprich das Sichern der Register (welche und wieviele das sind ist ja erstmal egal) auf dem Stack sollte auf jeder Architektur machbar sein. Implementierst du aber Hardware-Multitasking, wirst du andere Strukturen und wahrscheinlich auch nen ganz anderen Algo brauchen.

An diesem Bsp. geht es ja dann weiter, wenn die Register nicht auf dem Stack gesichert sind, musst du an vielen weiteren Stellen auch Code ändern. Obwohl das eigentlich gar nicht nötig wäre.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 15:05
Du musst sonst nirgends was ändern. Dein Pointer, den du in der Gegend rumreichst, zeigt halt nicht mehr auf den Stack, sondern ins TSS. Das ist alles, was sich ändert.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 09. November 2010, 15:16
Mal was anderes, wird CR3 eigentlich jedes Mal neugeladen? Weil das wäre schon nen guter Grund kein Hardware-Multitasking zu nutzen (wenn man Threads unterstützt).

Außerdem macht das deinen Scheduler dann davon abhängig, weil du ja die TSS dann organisieren musst (du musst die dann ja im Scheduler "verlinken") und nicht mehr einfach deine Thread-Diskriptoren.

Also ich denke du musst dann schon noch an anderen Stellen anderen Code verwenden wo du dir das ohne Hardware-Multitasking sparen könntest.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 15:33
Mal was anderes, wird CR3 eigentlich jedes Mal neugeladen? Weil das wäre schon nen guter Grund kein Hardware-Multitasking zu nutzen (wenn man Threads unterstützt).
Gute Frage, nächste. ;) Keine Ahnung, ehrlichgesagt. Wobei das ja sowieso keine Rolle mehr spielt, wenn der Kernel sein eigenes PD braucht, dann muss man ja auf jeden Fall wechseln.

Zitat
Außerdem macht das deinen Scheduler dann davon abhängig, weil du ja die TSS dann organisieren musst (du musst die dann ja im Scheduler "verlinken") und nicht mehr einfach deine Thread-Diskriptoren.
Hm, dieses Zeug ist mir suspekt genug (aka Protected Mode macht dem taljeth auch nach fünf Jahren noch Angst ;)), dass ich diesen Teil dann wohl doch wieder in Software basteln würde und den Inhalt des TSS durch Paging austauschen oder so.

Aber ich bin mir nicht sicher, dass der Scheduler davon was wissen muss. Gehört das nicht alles mit in den Dispatcher wie das Sichern der Register selber auch?
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 09. November 2010, 17:19
Hallo,


Hm, weißt du zufällig, was Hardware-MT so langsam macht? Eventuell gerade, dass der TLB jedesmal geflusht wird? Irgendwas muss ja mehr gemacht werden, damit es langsamer wird. Weiß zufällig jemand Bescheid?
Einer der Nachteile beim HW-Task-Wechsel auf x86 ist das alle Segment-Register neu geladen werden, das bedeutet 6 Descriptor-Zugriffe (und die können schon recht teuer werden wenn ein Segment noch nicht als accessed markiert ist o.ä.) und diese Descriptoren werden dann noch auf Gültigkeit geprüft (das heißt ist Executable für CS oder Readable and Writeable für SS und dazu noch diese DPL/CPL-Sachen). Ich denke gerade weil man sich (in einem Flat-Memory-OS) das Neuladen der Segmentregister spart ist auf x86 SW-Multitasking schneller. Es stimmt natürlich auch das AMD und Intel hier seit 20 Jahren keinerlei Optimierungsmöglichkeiten mehr genutzt haben, bei mir werde ich ja immerhin 16 Segmentregister (per SW) laden müssen und da will ich mit Hintergrund-Pipelining (weil der Kernel-Code diese Segmente ja gar nicht benutzt müssen die Schattenregister mit den decodierten Descriptoren auch nicht sofort zur Verfügung stehen so das die CPU in der Zeit weitere Befehle ausführen kann) einiges rausholen.
Das zwangsweise Neuladen von CR3 tut sein übriges, wobei es doch da jetzt dieses Global-Flag gibt (oder wie das heißt).

Wir reden hier eh über x86 und teilweise x86-spezifische Probleme. Interrupthandling ist nie portabel.
Die Stubs sind nie portabel (die sind immer CPU-abhängig und daher wohl auch immer in Assembler geschrieben) aber die eigentlichen (in einer Hochsprache geschriebenen) Interrupthandler sollten portabel sein (vorausgesetzt die zugehörige HW-Komponente ist identisch).


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 09. November 2010, 17:27
Bei einem Ringwechsel kommt man nicht drum herum, die Segmentregister neu zu laden. Man kann sich höchstens fs und gs sparen (oder wenn man TLS haben will, nur noch eins davon).

Bei den Interrupthandlern hast du natürlich recht, das war schlampig formuliert.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 09. November 2010, 22:18
Hallo,


Bei einem Ringwechsel kommt man nicht drum herum, die Segmentregister neu zu laden.
Sicher? im TSS sind die doch nur ein mal drin, vom SS mal abgesehen, und CS kommt von Interrupt-Gate. Wenn man für die Daten nur Ring3 braucht dann sollte IMHO auch der Ring 0 Code damit zurecht kommen, kleinerer aktueller Ring geht immer dachte ich eigentlich.
Oder irre ich mich da total?  (der x86-PM kann schon ziemlich verwirrend sein :roll: )
Dieses Problem müsste doch dann auch bei Call-Gates existieren, da könnte man dann ja nie einen FAR-Pointer an Code mit kleinerem Ring übergeben.


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 10. November 2010, 08:30
Zitat von: erik
Wenn man für die Daten nur Ring3 braucht dann sollte IMHO auch der Ring 0 Code damit zurecht kommen, kleinerer aktueller Ring geht immer dachte ich eigentlich.
Und welche Fälle fallen dir ein wo du ne Funktion vom UserMode aus aufrufst die dann nur mit den Daten aus dem UserMode läuft (ich hoffe dir fällt auf wie sinnlos das ist)?
Denn sobald du auf KernelMode Daten zugreifen willst geht das ja nicht, weil die ja genau gegen sowas geschützt sind und du dann nen KernelMode Datensegment brauchst.

Zitat von: erik
Dieses Problem müsste doch dann auch bei Call-Gates existieren, da könnte man dann ja nie einen FAR-Pointer an Code mit kleinerem Ring übergeben.
Doch, entweder du benutzt kein Paging dann sollte es eh gehen (wozu sind da die Ringe überhaupt da?) und wenn du Paging benutzt dann geht es um das kleine aber feine Flag was zw User- und KernelMode entscheidet und da ein User dir immer ein Segment mitgibt was auf UserMode-Daten zeigt, funktioniert das eben.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 10. November 2010, 10:41
Hallo,


Und welche Fälle fallen dir ein wo du ne Funktion vom UserMode aus aufrufst die dann nur mit den Daten aus dem UserMode läuft (ich hoffe dir fällt auf wie sinnlos das ist)?
Es geht hier doch um die 4G-Segmente in einem Flat-Memory-System (das Ring-0-Code niemals nur mit Ring-3-Daten arbeitet ist mir völlig klar, dann würde ja Ring-3-Code reichen). Die 2 typischen Data-Segmente (einmal für Ring 0 und einmal für Ring 3) zeigen doch auf den selben virtuellen Speicher (eben die vollen 4GB) was bedeutet das der User-Mode-Code theoretisch auch volle 4GB ansprechen kann, nur das besagte Flag in dem Page-Descriptoren dient da noch als Schutz. Nur allein dieses Flag verhindert das Ring-3-Code in den Kernel-Bereich rein kann. Als zusätzliche Sicherheit könnte man noch das Limit in den Ring-3-Descriptoren auf 3GB beschränken aber dann muss man wirklich wechseln.

Ich hab extra noch mal hier (http://en.wikipedia.org/wiki/Privilege_level) nachgelesen und ich bin schon der Meinung das man bei einem Syscall nicht DS und ES wechseln muss (nur CS und SS werden von der CPU automatisch gewechselt) weil der Kernel im Ring 0 ja trotzdem mit DS und ES (DPL=3 und RPL=3) die gesamten 4GB virtuellen Adressraum ansprechen kann. Selbst beim Paging gibt es keine Probleme weil das von Dir erwähnte Flag ja wimre gegen CPL (und die ist 0 im Kernel weil CS ja automatisch gewechselt wird) geprüft wird.
Es kann natürlich sein das ich mich total irre, meine x86-Kenntnisse sind etwas eingerostet, aber ich bin schon der Meinung das Ring-0-Code auch über ein Ring-3-Segment mit dem Speicher ganz normal arbeiten kann.

Das mit dem Call-Gate ist folgender Gedanke: wenn Ring-3-Code per Call-Gate eine Ring-0-Funktion aufruft (welche dann auch wirklich mit Ring 0 läuft) und dieser einen FAR-Pointer (Selector mit RPL=3 und im Descriptor ist DPL=3) mitgibt so kann doch der Ring-0-Code problemlos mit diesem Pointer auf Speicher zugreifen. Wenn das nicht ginge könnte der Ring-0-Code ja niemals mit den Nutzdaten des Ring-3-Codes arbeiten oder er müsste jedes mal den Selector modifizieren (wegen dem RPL) und auch noch den Decriptor in der GDT/LDT ändern (wegen dem DPL) und das wäre IMHO völlig unpraktikabel.

Ich befürchte ich hab da irgendwo einen Denkfehler, nur wo?
(ich bin doch ziemlich froh mich bei meinen Segmentierungsplänen gegen x86 entschieden zu haben, der ganze CPL/RPL/DPL-Kram macht einen noch ganz verrückt)


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 10. November 2010, 10:50
Ich denke, du hast in beiden Fällen recht.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 10. November 2010, 11:02
Hallo,


Ich denke, du hast in beiden Fällen recht.
Ich fürchte das ich Deinen Optimismus nicht teilen kann, irgendeinen Grund muss es doch geben das alle x86-OSe 4 Descriptoren in die GDT packen obwohl doch theoretisch (wenn meine Erklärungen stimmen würden) auch 2 reichen täten.


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 10. November 2010, 11:42
Ich glaube, ss muss im Kernel Ring 0 bleiben, aber sicher bin ich mir nicht. Und auch sonst wären es immer noch drei, weil das Codesegment auf jeden Fall bleiben muss.

Ich hab mal testweise im Interrupt-Stub von tyndur das Laden der Ring-0-Deskriptoren für ds und es rausgeworfen und es hat ohne irgendwelche Auffälligkeiten zur Shell gebootet.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 10. November 2010, 13:16
Zitat von: erik
Als zusätzliche Sicherheit könnte man noch das Limit in den Ring-3-Descriptoren auf 3GB beschränken aber dann muss man wirklich wechseln.
Es ging ja damals darum, dass sich Segmente nicht durchgesetzt haben und auf anderen Architekturen gab es halt sowas nicht. Deswegen nimmt man heute nur noch das FlatMemoryModel und regelt die Sicherheit über die Flags in den Paging Tabellen.

Zitat von: taljeth
Ich hab mal testweise im Interrupt-Stub von tyndur das Laden der Ring-0-Deskriptoren für ds und es rausgeworfen und es hat ohne irgendwelche Auffälligkeiten zur Shell gebootet.
Ich habe mal das selbe bei mir gemacht und funktioniert auch.

Jetzt bin ich aber auch baff. Denn wenn man sich das sparen kann, wäre das schon nicht schlecht.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Jidder am 10. November 2010, 13:17
Kann man sich nicht sparen. Ring 3 Code kann die Segment Register mit 0 laden und dann knallts im Kernel.

Edit: Man braucht außerdem einen Ring 0 Datendeskriptor, weil RPL und DPL von SS (bzw. dem Deskriptor) dem CPL entsprechen müssen.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 10. November 2010, 13:24
Sehr guter Einwand!
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 10. November 2010, 14:02
Hallo,


Kann man sich nicht sparen. Ring 3 Code kann die Segment Register mit 0 laden und dann knallts im Kernel.
Und? Dann gibt es im Kernel ne Exception und die biegt DS, ES, FS und GS wieder gerade und als Straffe für den Prozess (der diese Schandtat begangen hat) wird dieser gekillt, fertig. Dafür kann man sich das Neuladen von 4 Segmentregistern im Interrupt-Stub sparen, in einem Flat-Memory-OS sind die doch eh immer gleich und da sollte man diesen Performance-Vorteil ruhig mitnehmen. Oder sieht da jemand irgendwelche ernsten Gefahren?

Man braucht außerdem einen Ring 0 Datendeskriptor, weil RPL und DPL von SS (bzw. dem Deskriptor) dem CPL entsprechen müssen.
Aha, gut das wusste ich nicht.
Aber ein Argument warum man sich das Kernel-Code-Segment nicht sparen kann gibt es scheinbar noch nicht, aber es geht mir auch nicht darum in der GDT ein paar Bytes zu sparen (das bringt IMHO wahrlich nicht viel) sondern darum das ein Neuladen der Segment-Register eigentlich nicht erforderlich ist.


Es ging ja damals darum, dass sich Segmente nicht durchgesetzt haben und auf anderen Architekturen gab es halt sowas nicht.
Es ging in der Frage, auf die ich geantwortet hatte, ausdrücklich um das HW-Multitasking von x86 und nicht um irgendwelche anderen Architekturen.

Deswegen nimmt man heute nur noch das FlatMemoryModel und regelt die Sicherheit über die Flags in den Paging Tabellen.
Du vergisst da jemanden!


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 10. November 2010, 14:03
Kann man sich nicht sparen. Ring 3 Code kann die Segment Register mit 0 laden und dann knallts im Kernel.
Ich wusste doch, dass da irgendwo noch ein Problem ist, aber dieses Szenario war zu einfach. ;)

Zitat
Edit: Man braucht außerdem einen Ring 0 Datendeskriptor, weil RPL und DPL von SS (bzw. dem Deskriptor) dem CPL entsprechen müssen.
Ja, das meinte ich.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Jidder am 10. November 2010, 14:54
Kann man sich nicht sparen. Ring 3 Code kann die Segment Register mit 0 laden und dann knallts im Kernel.
Und? Dann gibt es im Kernel ne Exception [...]
Exceptions im Kernel sind keine gute Idee.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 10. November 2010, 15:18
Hallo,


Exceptions im Kernel sind keine gute Idee.
Dem kann ich nur voll und ganz zustimmen (auch wenn FlashBurn das sicherlich anders sieht).
Trotzdem bietet x86 eben diese Möglichkeit und an dieser konkreten Stelle finde ich das auch recht sinnvoll. Man benutzt eben ein architektur-spezifisches Feature um ein architektur-spezifisches Problem zu lösen. ;)


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 10. November 2010, 21:26
Zitat von: erik
Dem kann ich nur voll und ganz zustimmen (auch wenn FlashBurn das sicherlich anders sieht).
Habe ich sowas mal irgendwann gesagt  :?

Denn ich sehe es auch, Exceptions sollte man aus dem Kernel raushalten!
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 10. November 2010, 23:42
Hallo,


Zitat von: erik
Dem kann ich nur voll und ganz zustimmen (auch wenn FlashBurn das sicherlich anders sieht).
Habe ich sowas mal irgendwann gesagt  :?
Aber Du bist doch so sehr für einen unterbrechbaren Kernel eingetreten und wenn Du HW-IRQs im Kernel willst dann sind Exceptions auch nicht mehr schlimm. Trotzdem sorry das ich Dich da falsch eingeschätzt hab.


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 11. November 2010, 11:00
Zitat von: erik
Aber Du bist doch so sehr für einen unterbrechbaren Kernel eingetreten und wenn Du HW-IRQs im Kernel willst dann sind Exceptions auch nicht mehr schlimm.
Das sind für mich 2 Paar Schuhe.

Das eine (HW-IRQs) sind einfach nur Unterbrechungen, wie sie in jedem UserApp auch vorkommen und das andere (Exceptions) sind Fehler! Letztere möchte ich nicht im Kernel behandeln, denn Exception könnte bedeuten das ich den Fehler nicht behandeln kann und das Programm muss gekillt werden, versuch das mal mit deinem Kernel ;)

Eine Exception im Kernel heißt bei mir grundsätzlich PANIC().
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 11. November 2010, 12:37
Exceptions sind nicht grundsätzlich Fehler, die können auch eingeplant sein. Klassisches Beispiel ist der Page Fault beim Swapping.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 11. November 2010, 12:43
Hallo,


Zitat von: erik
Aber Du bist doch so sehr für einen unterbrechbaren Kernel eingetreten und wenn Du HW-IRQs im Kernel willst dann sind Exceptions auch nicht mehr schlimm.
Das sind für mich 2 Paar Schuhe.
Aber NMI benutzen, das nenne ich konsequent! ;)

Letztere möchte ich nicht im Kernel behandeln, denn Exception könnte bedeuten das ich den Fehler nicht behandeln kann und das Programm muss gekillt werden, versuch das mal mit deinem Kernel ;)
Klar will man den Kernel nicht killen aber gerade bei diesem speziellen Fehler "verbogene Segmentregister" ist es eindeutig das nicht der Kernel sondern ein User-Mode-Prozess gekillt werden muss. Ich bin schon der Meinung das es sich hierbei um eine spezielle Situation handelt für die man auch mal eine Ausnahme von der Regel machen kann (bekommst ja auch etwas Performance dafür geschenkt), aber wenn Du das anders siehst dann ist das Okay für mich.

Eine Exception im Kernel heißt bei mir grundsätzlich PANIC().
Bei mir auch, das ist sogar von der HW so vorgegeben.


Grüße
Erik
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 11. November 2010, 13:00
Zitat von: erik
Aber NMI benutzen, das nenne ich konsequent! Wink
Ich überlege immer nebenher, wie ich diesen NMI wieder loswerden kann ;)

Denn das Problem ist, wie kann ich zw. nem richtigen NMI und ner IPI-Nachricht unterscheiden?

Zitat von: erik
aber gerade bei diesem speziellen Fehler "verbogene Segmentregister" ist es eindeutig das nicht der Kernel sondern ein User-Mode-Prozess gekillt werden muss.
Ich bin gerade zu faul in den Intel Manuals nachzugucken, aber wie bekommt man eigentlich raus das eins (und vorallem welches es dann ist) falsch war?

Eine andere Situation, wäre wenn man bei mir einfach den Wert aus fs (ist fürs TLS) in ds oder es schreibt. Eigentlich müsste man da ja auch ne Exception bekommen, wenn man außerhalb des Segments zugreifen will, oder?
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: Jidder am 11. November 2010, 13:26
Ich bin gerade zu faul in den Intel Manuals nachzugucken, aber wie bekommt man eigentlich raus das eins (und vorallem welches es dann ist) falsch war?
Dass eins falsch war, bekommt man mit einem General Protection Fault mit. Welches das ist, nur durch den nachfolgenden Einsatz eines Disassemblers. Aber man muss eh alle Register mit korrekten Werten neuladen, wenn ein GPF auftritt, siehe unten.

Man benutzt eben ein architektur-spezifisches Feature um ein architektur-spezifisches Problem zu lösen. ;)
Es gab kein Problem, also wurde auch keines nicht gelöst. Wenn man hingegen deine Idee einmal weiterdenkt, dann stößt man auf Probleme.

- Der GPF-Handler muss ein Sonderfall werden, weil der ja nicht wieder über die sabotierten Segment Register stolpern soll. Also muss er immer die Segment Register neuladen.

- Wenn man den Virtual-8086 Mode unterstützen will, dann muss man auch in allen IRQ-Handlern und in den meisten Exception-Handlern die Register neuladen, weil alle Exceptions und Interrupts aus dem Virtual-8086 Mode mit genullten Segment Registern im Kernel ankommen.

- Man muss weiterhin darauf aufpassen, dass kein Interrupt-Handler Locks annimmt. Weil diese Exception könnte auftreten, während ein Lock gehalten wird. Da lässt der Dead Lock dann nicht lange auf sich warten.

- Ich nehme mal an, dass es im Kernel sowas wie eine globale (cpu-lokale) Variable "current_task" gibt, und dass das die einzige Möglichkeit ist, im Exception Handler festzustellen, welcher Task der Verursacher der Exception war. Man muss jetzt aufpassen, dass diese Exception nicht auftritt, nachdem ein Kontext Wechsel stattgefunden hat, also current_task geändert wurde. Sonst würde der falsche Task gekillt werden. Ich sehe keine Möglichkeit das zu garantieren, außer durch Neuladen der Segment Register.

Ich finde eriks Idee immer besser.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 11. November 2010, 13:45
Zitat von: taljeth
Exceptions sind nicht grundsätzlich Fehler, die können auch eingeplant sein. Klassisches Beispiel ist der Page Fault beim Swapping.
Swapping habe ich noch nicht, aber recht hast du trotzdem, hatte mal mit dem Gedanken gespielt lazy mapping im Kernel zuzulassen.
Aber Swapping möchte ich im Kernel sowieso nicht haben.

Zitat von: porkchicken
Dass eins falsch war, bekommt man mit einem General Protection Fault mit.
Das ist mir schon klar, aber nen GPF wird ja nicht nur deswegen, sondern auch noch aus anderen Gründen geworfen. Du müsstest also erstmal rausfinden das ein fehlerhaftes Segment Register der Grund war und dann musst du noch unterscheiden ob es einfach "nur" ein Zugriff über Segmentgrenzen hinaus war (ist bei mir bei TLS möglich).

Zitat von: porkchicken
Welches das ist, nur durch den nachfolgenden Einsatz eines Disassemblers.
Wenn man davon ausgeht, das es eh nur ds, es, fs oder gs sein können die falsch sind, dann wäre es doch einfacher, sie entweder mit Standardwerten zu laden oder einfach die 4 zu überprüfen, aber ich glaube nicht das man einen Disassembler dafür bräuchte.

Zitat von: porkchicken
Ich finde eriks Idee immer besser.
Ich bin mir gerade nicht sicher ob du das ironisch oder ernst meinst ;)
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 11. November 2010, 14:14
Swapping habe ich noch nicht, aber recht hast du trotzdem, hatte mal mit dem Gedanken gespielt lazy mapping im Kernel zuzulassen.
Aber Swapping möchte ich im Kernel sowieso nicht haben.
Ich sage ja nicht, dass du das im Kernel benutzen willst. Ich widerspreche nur der Behauptung, dass eine Exception immer ein Fehler ist. tyndur plant Exceptions an ein paar Stellen fest ein, aber die sind auch alle nur für Userspace.

Zitat
Zitat von: porkchicken
Ich finde eriks Idee immer besser.
Ich bin mir gerade nicht sicher ob du das ironisch oder ernst meinst ;)
Hm, der Smiley verunsichert mich. Meinst du das jetzt ironisch oder ernst? ;)
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: FlashBurn am 11. November 2010, 15:27
Zitat von: taljeth
Ich widerspreche nur der Behauptung, dass eine Exception immer ein Fehler ist.
Doch ;)

Eine Exception tritt nur auf wenn auch ein Fehler vorliegt (ob das nun ist, weil eine Page nicht vorhanden ist und aus dem Swapp-Speicher geholt werden muss oder eine Division durch 0)!
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: kevin am 11. November 2010, 15:49
Wenn man sich die Definitionen zurechtbiegt, kann man natürlich alles beweisen. ;) Für mich ist etwas kein Fehler, wenn es normaler Teil des Programmablaufs ist.
Titel: Re:Adressraum für Kernel und Prozesse
Beitrag von: erik.vikinger am 11. November 2010, 19:37
Hallo,


Denn das Problem ist, wie kann ich zw. nem richtigen NMI und ner IPI-Nachricht unterscheiden?
Sollte man im local APIC nicht rausbekommen ob er den NMI ausgelöst hat?


Also muss er immer die Segment Register neuladen.
Das sollten vielleicht alle Expection-Handler (Vectoren 0x00...0x1F) machen. Bremst ja nicht die Performance vom Syscall und dem Context-Switch-IRQ aus und um die geht es doch.

weil alle Exceptions und Interrupts aus dem Virtual-8086 Mode mit genullten Segment Registern im Kernel ankommen.
Hm, das wusste ich nicht, ich hab mich auch nie mit dem VM86 beschäftigt. Das ist schon eine gewisse Einschränkung.

Weil diese Exception könnte auftreten, während ein Lock gehalten wird.
Nicht wenn man dafür sorgt das noch relativ am Anfang der Assembler-Interrupt-Stubs DS und ES verwendet werden (einfach bei 2 Speicherzugriffen passende Präfixe benutzen) , FS und GS sind erst mal egal weil der vom Compiler erzeugte Kernel-Code die wohl nie benutzen wird.

und dass das die einzige Möglichkeit ist, im Exception Handler festzustellen, welcher Task der Verursacher der Exception war.
Die selbe Lösung wie zuvor.

Ich finde eriks Idee immer besser.
Meinst Du das ernst? (ja, ich meine meine Frage ernst und benutze hier absichtlich kein Smiley)


Grüße
Erik