Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: FlashBurn am 06. September 2010, 13:34

Titel: Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 13:34
Beim Thema IPC Methoden wurde es mal ganz kurz angerissen, das Thema Treiber. Bei einem Mikrokernel ist das Thema nicht so einfach.

Um was es mir aber genau geht, ein Treiber braucht oft (??) die physikalische Adresse einer virtuellen (da DMA kein Paging kennt) und das erste Problem wäre die Sicherheit, ich möchte eigentlich nicht jedem Prozess erlauben rauszubekommen welche physikalische Adresse hinter einer virtuellen steckt.

Aber was wäre das Problem wenn dem so wäre, sprich was könnte ein Prozess damit anfangen?

Ich überlege einfach die Pagingtabellen für Treiber "freizugeben", sprich die können lesend darauf zugreifen (natürlich nur auf den UserSpace-Teil). Was haltet ihr davon? Der Vorteil wäre die Performance, da dadurch Syscalls entfallen würden.

Nächstes Problem wäre, wie bekommt man den Speicher eines Geräts, z.B. den Framebuffer einer Graka, in den Adressraum des Treibers?

Das Problem was ich habe, ist das die ganzen Geräte nicht im Kernel sondern in einem Device-Server verwaltet werden und es so schwieriger wird solchen Speicher zu mappen, weil auch da wieder die Frage ist, wie bekomme ich diesen Speicher in den Device-Server?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 14:09
Hallo,

wenn ich als Bösling die physikalische Adresse einer virtuellen Adresse herausbekommen kann, kann ich mittels Buffer-Overflows etc. in den Treibern mittels DMA Codebereiche überschreiben (lassen), die dann später gezielt zur Ausführung gebracht werden. DMA kennt auch keine Sicherheitsmaßnahmen.

Das gesamte Mapping von Speicherbereichen obliegt dem Memory Manager. Das heißt, dein Treiber fordert halt eine gewisse Menge (physikalisch addressierten) Speicher an, die dann in seinen virtuellen Adressraum gemappt wird. Dieser Speicher wird dann zur Kommunikation mit dem Gerät benutzt. Diese Zuordnung ändert sich auch nicht besonders oft, daher solltest du das per Syscall/IPC (an den Memory Manager) machen können.

Zitat
Treiber: "Ich brauche 32 KB ab <phys.adr.>" (Geräte-Konfigregister)
MM:      "Gut, findest du ab <virt.adr.> in deinem Adressraum."
Treiber: "Und ich brauche 64 KB mit 8K-Alignment unterhalb 16 MB" (Geräte-Datenaustausch)
MM:      "Gut, hast du ab <phys.adr.> bei dir im Adressraum ab <virt.adr.>"

Treiber können dann noch eine besondere Privilegierungsstufe bekommen, sodaß normaler Userspace eben nicht den physischen Adressraum benutzen kann. Mit dieser Variante brauchen auch Treiber nicht zwischen physisch und virtuell umrechnen - das erledigt die Speicherverwaltung. Die hat die Daten eh vorliegen und kümmert sich um die Reservierungen.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 14:16
Also erstmal das wichtigste: Es heißt physisch, nicht physikalisch. ;)

Ich glaube, was Svenska beschreibt ist das, was tyndur macht. Wenn ein Treiber physischen Speicher einfach irgendwo haben will, dann fordert er vom Kernel Speicher an, setzt aber die Flags passend, damit der Speicher physisch zusammenhängend ist und sowohl virtuelle als auch physische Adresse zurückgegeben werden.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 15:21
Zitat von: taljeth
Also erstmal das wichtigste: Es heißt physisch, nicht physikalisch.
Wird Zeit das ich wach werde ;)

Mit dem Konzept habe ich so meine Probleme. Wie gehst du sicher das ein Treiber auch nur den Speicher mappt der zu dem Gerät gehört? Ansonsten könnte ein Treiber ja sonstwas für Speicher mappen.
Das nächste ist, ihr geht hier nur von MemoryMapped-IO aus, ich meine aber auch, das du halt einfach sagst, ich (der Treiber) brauche mal 64kb Speicher, brauche die physische Adresse von jeder 4KB Page, damit ich da was reinladen lassen kann.

Auch finde ich es nicht passend das ihr davon ausgeht das der physische Speicher zusammenhängend ist. Erstens kann das mein PMM nicht wirklich und zweitens, was wird gemacht, wenn zwar genug Speicher, aber halt kein zusammenhängender Speicher vorhanden ist?

Zitat von: svenska
wenn ich als Bösling die physikalische Adresse einer virtuellen Adresse herausbekommen kann, kann ich mittels Buffer-Overflows etc. in den Treibern mittels DMA Codebereiche überschreiben (lassen), die dann später gezielt zur Ausführung gebracht werden. DMA kennt auch keine Sicherheitsmaßnahmen.
Sorry, aber das Problem hast du so oder so! Ich meine, man muss schon davon ausgehen, das man einem Treiber vertrauen kann. Denn wie willst du sicher stellen, das ein Treiber die HDD dazu instruiert wirklich nur in den Speicherbereich zu schreiben der dafür vorgesehen ist und nicht irgendwelchen vorhandenen Code überschreibt?

Zitat von: svenska
Treiber können dann noch eine besondere Privilegierungsstufe bekommen, sodaß normaler Userspace eben nicht den physischen Adressraum benutzen kann. Mit dieser Variante brauchen auch Treiber nicht zwischen physisch und virtuell umrechnen - das erledigt die Speicherverwaltung. Die hat die Daten eh vorliegen und kümmert sich um die Reservierungen.
Das habe ich mal gar nicht verstanden ;)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 15:46
Mit dem Konzept habe ich so meine Probleme. Wie gehst du sicher das ein Treiber auch nur den Speicher mappt der zu dem Gerät gehört? Ansonsten könnte ein Treiber ja sonstwas für Speicher mappen.
Dein Memory Manager hat den Überblick über den gemappten physischen Speicher. Wenn also ein Treiber bereits gemappten physischen Speicher haben will, wird der Request abgelehnt. Außerdem, wenn ich physischen Speicher möchte, ist es mir ja erstmal egal, wo der liegt - die Adresse kann ich dann ja in die Hardware reinprogrammieren.

Du musst dem Treiber schon soweit vertrauen, dass er nicht 2GB physischen Speicher am Stück will. Und wenn doch, kannst du immernoch ablehnen.

Das nächste ist, ihr geht hier nur von MemoryMapped-IO aus, ich meine aber auch, das du halt einfach sagst, ich (der Treiber) brauche mal 64kb Speicher, brauche die physische Adresse von jeder 4KB Page, damit ich da was reinladen lassen kann.
Naja, physischen Speicher brauchst du für zwei Dinge: Datenaustausch mit dem Gerät über DMA und Konfiguration des Gerätes, wenn es über MMIO angebunden ist. Letzteres entfällt natürlich, wenn du über Ports/GPIOs/sonstwas an das Gerät rankommst. Ersteres entfällt, wenn du die Daten irgendwie anders aus dem Gerät rauspopelst (PIO). Dann brauchst du aber auch kein Mapping physisch<->virtuell.

Auch finde ich es nicht passend das ihr davon ausgeht das der physische Speicher zusammenhängend ist. Erstens kann das mein PMM nicht wirklich und zweitens, was wird gemacht, wenn zwar genug Speicher, aber halt kein zusammenhängender Speicher vorhanden ist?
Dann geht das halt nicht, ganz einfach. Wenn mein Gerät DMA machen möchte, muss ich mindestens einen DMA-Block physisch zusammenhängend bereitstellen. Und wenn ich gern "schnell" hätte, muss ich halt mehrere solcher Blöcke haben - im einfachsten Fall als ein großer Block. Ist aber Sache des Treibers, wieviele Blöcke ich welcher Größe wo brauche. In meinem Beispiel sind das einfach 2 Blöcke, die müssen auch nicht hintereinander liegen.

Zitat von: svenska
wenn ich als Bösling die physikalische Adresse einer virtuellen Adresse herausbekommen kann, kann ich mittels Buffer-Overflows etc. in den Treibern mittels DMA Codebereiche überschreiben (lassen), die dann später gezielt zur Ausführung gebracht werden. DMA kennt auch keine Sicherheitsmaßnahmen.
Sorry, aber das Problem hast du so oder so! Ich meine, man muss schon davon ausgehen, das man einem Treiber vertrauen kann. Denn wie willst du sicher stellen, das ein Treiber die HDD dazu instruiert wirklich nur in den Speicherbereich zu schreiben der dafür vorgesehen ist und nicht irgendwelchen vorhandenen Code überschreibt?
Korrekt. Ich dachte, du bezogst dich an der Stelle auf Prozesse allgemein (also nicht nur Treiber). Und du hast ziemlich allgemein gefragt.

Zitat von: svenska
Treiber können dann noch eine besondere Privilegierungsstufe bekommen, sodaß normaler Userspace eben nicht den physischen Adressraum benutzen kann. Mit dieser Variante brauchen auch Treiber nicht zwischen physisch und virtuell umrechnen - das erledigt die Speicherverwaltung. Die hat die Daten eh vorliegen und kümmert sich um die Reservierungen.
Das habe ich mal gar nicht verstanden ;)
Es gibt Anwendungen - es gibt Treiber - und es gibt den Memory Manager. Letzterer darf alles. Treiber dürfen ihren (phys.) Speicher beim Memory Manager beantragen. Anwendungen haben keine Möglichkeit, physische Adressen zu bekommen oder zu ermitteln. Damit können nur Treiber gezielt böse Sachen mit DMA machen, Anwendungen leben ausschließlich im virtuellen Adressraum.

Hoffe, das war verständlicher.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 15:46
Mit dem Konzept habe ich so meine Probleme. Wie gehst du sicher das ein Treiber auch nur den Speicher mappt der zu dem Gerät gehört?
Kann ich nicht, der Kernel hat keine Ahnung von PCI (oder was auch immer). Klassische Lösung: Alles was als root läuft (oder sonst irgendeine Art von Recht hat), darf das.

Zitat
Das nächste ist, ihr geht hier nur von MemoryMapped-IO aus, ich meine aber auch, das du halt einfach sagst, ich (der Treiber) brauche mal 64kb Speicher, brauche die physische Adresse von jeder 4KB Page, damit ich da was reinladen lassen kann.
Das ist doch genau der Fall, den ich beschrieben habe?

Zitat
Auch finde ich es nicht passend das ihr davon ausgeht das der physische Speicher zusammenhängend ist. Erstens kann das mein PMM nicht wirklich und zweitens, was wird gemacht, wenn zwar genug Speicher, aber halt kein zusammenhängender Speicher vorhanden ist?
Mit virtuell zusammenhängend kann die Hardware aber dummerweise nichts anfangen. Wenn du nicht mehrere Pages physisch zusammenhängend zur Verfügung stellen kannst, musst du dich eben einschränken und maximal 4k auf einmal an die Hardware übergeben.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 16:15
Zitat von: taljeth
Kann ich nicht, der Kernel hat keine Ahnung von PCI (oder was auch immer). Klassische Lösung: Alles was als root läuft (oder sonst irgendeine Art von Recht hat), darf das.
Und genau das möchte ich bei mir nicht, mit Ports ist das noch relativ einfach und wenn ich eine Möglichkeit gefunden habe, bestimmten Speicher nur in meinem Device-Server zuzulassen, dann habe ich auch das Problem gelöst (ich "vererbe" den Speicher dann einfach an die Treiber, das wäre die Lösung für MemoryMapped-IO).

Zitat von: taljeth
Das ist doch genau der Fall, den ich beschrieben habe?
Nur, will ich das der Speicher nicht unbedingt zusammenhängend sein muss und dann müsste man einen Syscall pro Page machen und das wäre mir halt doch ein wenig zuviel des Guten (würde aber für den Anfang funktionieren) und deswegen dachte ich daran, einfach den Treiber lesend auf die PageTables zugreifen zu lassen.

Zitat von: taljeth
Mit virtuell zusammenhängend kann die Hardware aber dummerweise nichts anfangen. Wenn du nicht mehrere Pages physisch zusammenhängend zur Verfügung stellen kannst, musst du dich eben einschränken und maximal 4k auf einmal an die Hardware übergeben.
Genau so ist das geplant. Die einzige Möglichkeit an zusammenhängenden physischen Speicher zu kommen, ist es 4MB "direkt", also eine 4MB Page, (mein PMM unterstützt das ab 32MB RAM) anzufordern.

Zitat von: svenska
Dein Memory Manager hat den Überblick über den gemappten physischen Speicher.
Was meinst du genau mit "gemappten physischen Speicher"? Meinst du da welcher Speicher in Benutzung ist und welcher nicht?

Das kann mein PMM nicht so richtig. Ich weiß welcher Speicher frei ist, aber mehr auch nicht.

Zitat von: svenska
Außerdem, wenn ich physischen Speicher möchte, ist es mir ja erstmal egal, wo der liegt - die Adresse kann ich dann ja in die Hardware reinprogrammieren.
Wenn wir jetzt über MemoryMapped-IO reden, dann ist es unter Umständen nicht egal wo dieser physische Speicher liegt, bzw. sollte hinter einer MemoryMapped-IO Adresse (im besten Fall, wo also weit weniger als 4GB RAM vorhanden sind) kein physischer Speicher liegen, das Alignment macht dir nämlich einen Strich durch die Rechnung.
Soweit kommt es aber bei mir noch nicht, da ich noch keine Möglichkeiten habe, den Speicher für MemoryMapped-IO selbst zu bestimmen. Dazu müsste ich gezielt Speicher aus meinem PMM entfernen können.

Zitat von: svenska
Dann geht das halt nicht, ganz einfach. Wenn mein Gerät DMA machen möchte, muss ich mindestens einen DMA-Block physisch zusammenhängend bereitstellen. Und wenn ich gern "schnell" hätte, muss ich halt mehrere solcher Blöcke haben - im einfachsten Fall als ein großer Block. Ist aber Sache des Treibers, wieviele Blöcke ich welcher Größe wo brauche. In meinem Beispiel sind das einfach 2 Blöcke, die müssen auch nicht hintereinander liegen.
Das ist aber schlecht! Wie willst du nem User folgendes verklickern:

er hat zwar von seinen 2GB RAM noch 1GB frei, aber da der Speicher so fragmentiert ist dass jede 2. Page (physisch gesehen) in Benutzung ist, kann er keine Daten mehr von seiner HDD laden?

Das ist aber ein ganz schlechtes Konzept. Bevor du mir jetzt mit Paging und Swapping kommst, auch für das Swapping bräuchtest du dann ja mehrere zusammenhängende (physisch) Blöcke.

@svenska

Ich weiß nicht wie dein MemoryManager funktioniert, aber ich habe einen PMM und einen VMM. Der PMM ist einfach nur dafür verantwortlich, das man freien physischen Speicher von ihm bekommt und nicht mehr benötigten physischen (also vorhandener RAM) zurückgeben kann.
Der VMM kümmert sich einfach nur darum, welche virtuelle Adresse frei ist und welche nicht.

Der Punkt ist, mein PMM verwaltet nicht immer 4GB sondern nur soviel Speicher wie da ist.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 16:20
Nur, will ich das der Speicher nicht unbedingt zusammenhängend sein muss und dann müsste man einen Syscall pro Page machen und das wäre mir halt doch ein wenig zuviel des Guten (würde aber für den Anfang funktionieren) und deswegen dachte ich daran, einfach den Treiber lesend auf die PageTables zugreifen zu lassen.
Den Syscall brauchst du doch sowieso, damit du überhaupt Speicher bekommst, auch wenn er nur virtuell zusammenhängend ist?

Und außerdem würde die PT direkt lesen bedeuten, dass jeder Treiber das Page-Table-Layout kennen muss. Das gibt einen Spaß beim Portieren.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 16:43
Zitat von: taljeth
Den Syscall brauchst du doch sowieso, damit du überhaupt Speicher bekommst, auch wenn er nur virtuell zusammenhängend ist?
Ja, ich meine aber das:

- Du forderst 64KB an
- bekommst eine virtuelle Adresse zurück
- jetzt machst du für jede 4KB Page einen Syscall um die physische Adresse rauszubekommen

Was man machen könnte, ist einen extra Syscall für Treiber zu implementieren, dem man einen Pointer übergibt, wo man die physischen Adressen des virtuellen Speichers (der angefordert wurde) reinschreibt.

Zitat von: taljeth
Und außerdem würde die PT direkt lesen bedeuten, dass jeder Treiber das Page-Table-Layout kennen muss. Das gibt einen Spaß beim Portieren.
Portabler Code ist nicht wirklich eins meiner Ziele (auch wenn ich es im Hinterkopf habe). Dazu kommt noch, was ist an "getPhysAddr(void *virtAddr)" unportabel? Ich meine, du lagerst das einfach in eine Funktion in einer Bibliothek aus und wie das dann in der Bibliothek implementiert ist, kann dir doch egal sein.

Mein Frage wäre bzw ist noch immer, ob durch das Lesen der PTs wirklich ein Sicherheitsproblem entsteht?

Wie wird der ganze Spaß denn in anderen Mikrokerneln gelöst (rausbekommen welche physische Adresse hinter einer virtuellen steckt)?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Jidder am 06. September 2010, 17:04
Ich überlege einfach die Pagingtabellen für Treiber "freizugeben", sprich die können lesend darauf zugreifen (natürlich nur auf den UserSpace-Teil). Was haltet ihr davon? Der Vorteil wäre die Performance, da dadurch Syscalls entfallen würden.

Zwischen Lesen und Verwenden der physischen Adresse (z.B. Versenden an die HW) vergeht eine gewisse Zeit, in der sich das Mapping ändern kann (Swapping, Copy-on-Write, verzögertes Mapping, MMIO, etc.) Dagegen hilft nur Locking, Pinning, ... wie auch immer man das nennen will. Auf jeden Fall musst du die Zuordnung auf die physischen Adressen in einen definierten Zustand bringen, was dich Syscalls kosten wird.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 17:07
Zitat von: PorkChicken
Zwischen Lesen und Verwenden der physischen Adresse (z.B. Versenden an die HW) kann eine gewisse Zeit vergehen, in der sich das Mapping ändern kann (Swapping, Copy-on-Write, verzögertes Mapping, MMIO, etc.) Dagegen hilft nur Locking, Pinning, ... wie auch immer man das nennen will. Auf jeden Fall musst du die Zuordnung auf die physischen Adressen in einen definierten Zustand bringen, was dich Syscalls kosten wird.
Würde ich einfach als Flag ("UNSWAPABLE") implementieren, welches dann natürlich nur von Treibern benutzt werden darf, bzw. da ich ohnehin plane solche Buffer dann als SharedMem an andere Prozesse weiterzugeben wäre das Problem auch so gelöst (SharedMem wird bei mir auf keinen Fall ausgelagert).
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 17:45
Zitat von: taljeth
Kann ich nicht, der Kernel hat keine Ahnung von PCI (oder was auch immer). Klassische Lösung: Alles was als root läuft (oder sonst irgendeine Art von Recht hat), darf das.
Und genau das möchte ich bei mir nicht, mit Ports ist das noch relativ einfach und wenn ich eine Möglichkeit gefunden habe, bestimmten Speicher nur in meinem Device-Server zuzulassen, dann habe ich auch das Problem gelöst (ich "vererbe" den Speicher dann einfach an die Treiber, das wäre die Lösung für MemoryMapped-IO).
Du traust also dem Treiber zu, dass er nicht DMA auf "irgendwelchen" Speicher in die Hardware schreibt, traust ihm dann aber wieder nicht zu, dass er sich Speicher holen darf, den er braucht?

Zitat von: svenska
Dein Memory Manager hat den Überblick über den gemappten physischen Speicher.
Was meinst du genau mit "gemappten physischen Speicher"? Meinst du da welcher Speicher in Benutzung ist und welcher nicht?
Also, die gesamte Speicherverwaltung besteht aus physischem und virtuellem Adressraum, hinter dem jeweils teilweise Speicher steht. Und du musst wissen, welcher Speicher frei ist - getrennt für virtuellen und physischen Speicher, als auch die Verbindung zwischen beiden Adressräumen. Damit weißt du also, welcher Teil des physischen Speichers wo im virtuellen Speicher eines jeden Prozesses gemappt ist.

Zitat von: svenska
Außerdem, wenn ich physischen Speicher möchte, ist es mir ja erstmal egal, wo der liegt - die Adresse kann ich dann ja in die Hardware reinprogrammieren.
Wenn wir jetzt über MemoryMapped-IO reden, dann ist es unter Umständen nicht egal wo dieser physische Speicher liegt, bzw. sollte hinter einer MemoryMapped-IO Adresse (im besten Fall, wo also weit weniger als 4GB RAM vorhanden sind) kein physischer Speicher liegen, das Alignment macht dir nämlich einen Strich durch die Rechnung.
Hä?

Teile des physischen Adressraums sind nicht mit Speicher unterlegt, sondern mit Konfigurationsregistern der Hardware, meist jenseits des realen RAM-Ausbaus (z.B. jenseits der 2GB). Dort muss ein Treiber also unter Umständen physischen Adressraum in seinen eigenen virtuellen Adressraum mappen, der kein RAM ist.
Die Datenkommunikation zwischen Treiber und Hardware läuft dann wiederum über shared memory, wo die physische Adresse bekannt sein muss (wg. DMA). Also musst du auch dort physischen Adressraum, diesmal mit RAM, in den virtuellen Adressraum mappen können.

Wo die Adressen im virtuellen Adressraum landen, ist egal. Welche Adressen im physischen Adressraum benutzt werden, hängt konkret von der Hardware ab (Konfigurationsregister sind fest) und ist nur teilweise programmierbar (Zieladresse des DMA ist es).

Das gilt für MMIO. Wenn du über Ports zugreifst, hast du einen dritten Adressraum, der mit beiden anderen nichts zu tun hat. Für MMIO und DMA muss es auf jeden Fall die beschriebenen Möglichkeiten geben.

Wenn du nur reines PIO machst, brauchst du beides nicht. Welche dieser Möglichkeiten du brauchst, hängt halt konkret von der Hardware ab.

Soweit kommt es aber bei mir noch nicht, da ich noch keine Möglichkeiten habe, den Speicher für MemoryMapped-IO selbst zu bestimmen. Dazu müsste ich gezielt Speicher aus meinem PMM entfernen können.
Als "belegt" markieren reicht aus. Wie gesagt, Teile des physischen Adressraums, den du benötigst, sind nicht mit RAM unterlegt.

Zitat von: svenska
Dann geht das halt nicht, ganz einfach. Wenn mein Gerät DMA machen möchte, muss ich mindestens einen DMA-Block physisch zusammenhängend bereitstellen. Und wenn ich gern "schnell" hätte, muss ich halt mehrere solcher Blöcke haben - im einfachsten Fall als ein großer Block. Ist aber Sache des Treibers, wieviele Blöcke ich welcher Größe wo brauche. In meinem Beispiel sind das einfach 2 Blöcke, die müssen auch nicht hintereinander liegen.
Das ist aber schlecht! Wie willst du nem User folgendes verklickern:

er hat zwar von seinen 2GB RAM noch 1GB frei, aber da der Speicher so fragmentiert ist dass jede 2. Page (physisch gesehen) in Benutzung ist, kann er keine Daten mehr von seiner HDD laden?
Wenn der Treiber physisch 4 MB RAM unterhalb der 16 MB fordert (weil es halt ein popeliger ISA-SCSI-Controller ist), dann wird das wahrscheinlich nicht gehen. Wenn du aber gerne physisch 4 MB RAM als Block irgendwo möchtest, dann geht das wahrscheinlich schon. Ist der RAM voll, dann geht das eben nicht. Wie auch?

Außerdem sollte der Treiber für die Kommunikation mit dem Gerät den Speicher direkt beantragen, oder zumindest einen kleinen Block (z.B. 64 KB). Damit garantierst du auch bei voller Speicherauslastung, dass du die Hardware ansteuern kannst. Alternativ gehst du halt immer weiter runter, bis du einen physischen(!) Block entsprechender Größe bekommst. Dann holst du dir einen Dateisystemblock von der Festplatte halt nur in 4K-Häppchen.

Ich weiß nicht wie dein MemoryManager funktioniert, aber ich habe einen PMM und einen VMM. Der PMM ist einfach nur dafür verantwortlich, das man freien physischen Speicher von ihm bekommt und nicht mehr benötigten physischen (also vorhandener RAM) zurückgeben kann.
Richtig, und was deine Treiber möchten, ist die Möglichkeit, bestimmte und unbestimmte Bereiche zu bekommen.

Der VMM kümmert sich einfach nur darum, welche virtuelle Adresse frei ist und welche nicht.
Was auch hinreicht.

Der Punkt ist, mein PMM verwaltet nicht immer 4GB sondern nur soviel Speicher wie da ist.
Was nicht ausreicht, da der physische Adressraum halt 4GB groß ist und du dort (z.B. ab 3GB) den Framebuffer der Grafikkarte oder die PCI-Konfigurationsregister findest. Die musst du auch verwalten!

Ja, ich meine aber das:

- Du forderst 64KB an
- bekommst eine virtuelle Adresse zurück
- jetzt machst du für jede 4KB Page einen Syscall um die physische Adresse rauszubekommen

Was man machen könnte, ist einen extra Syscall für Treiber zu implementieren, dem man einen Pointer übergibt, wo man die physischen Adressen des virtuellen Speichers (der angefordert wurde) reinschreibt.
Warum so kompliziert? Was hat dein Treiber davon, wenn er sich jede einzelne Page, die er für die Kommunikation mit der Hardware braucht, einzeln anfordern muss? Außerdem garantierst du ja nicht, dass die Pages zusammenhängend sind.

Erklär du mal dem HDD-Controller, dass er die ersten 4 KB nach 0x3400 0000, die zweiten 4 KB nach 0x3800 0000 und die dritten 4 KB nach 0x3400 8000 schreiben soll. Das heißt, du programmierst die Hardware dreimal, um 12KB von der Festplatte zu lesen.

Implementier lieber zwei Funktionen:

*getPhysMem( int size, ptr physAddr )
-> gib mir "size" Bytes ab physisch "physAddr" zurück
=> malloc() mit gegebener Adresse für deinen PMM

*getPhysMem( int size, ptr *physAddr )
-> gib mir "size" Bytes Speicher und schreibe in "physAddr" die physische Adresse rein
=> malloc() mit Rückgabe der verwendeten physischen Adresse

Wenn du willst, kannst du noch einen Alignment-Parameter mit einbinden, wenn du z.B. Hardware hast, die ein Alignment >4K braucht.

Was du dir sparst:
- Prozesse müssen die PageTables nicht selbst parsen können (Portabilität, vgl. taljeth)
- Prozesse haben keine Möglichkeit, das Mapping zwischen virt. und phys. Adressraum rauszukriegen (Sicherheit)
- nur ein Syscall pro Treiber und Adressraumblock

Oder sage mir, warum mein Ansatz nicht geht.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 18:40
Zitat von: svenska
Du traust also dem Treiber zu, dass er nicht DMA auf "irgendwelchen" Speicher in die Hardware schreibt, traust ihm dann aber wieder nicht zu, dass er sich Speicher holen darf, den er braucht?
Naja, wenn du so ran gehst, dann brauchst du für einen Treiber gar keine Sicherheit! Wozu kontrollieren auf welche Ports der Treiber zugreifen darf?
Ich will, soweit es geht, ein wenig Sicherheit auch vor Treibern. Das ich mich nicht vor falschen DMA Adressen schützen kann, ist leider schade, aber damit muss ich leben.
Da ist der alte ISA DMA Kontroller natürlich besser zu kontrollieren. Denn den könntest du noch abstrahieren und selbst kontrollieren und die Treiber müssten dann alle DMA Anforderungen an dich (als z.B. Server) machen.

Zitat von: svenska
Damit weißt du also, welcher Teil des physischen Speichers wo im virtuellen Speicher eines jeden Prozesses gemappt ist.
Mein Problem hier ist, meinst du damit auch, dass ich wissen müsste in welchem Prozess die Page 0x1000 ist? Denn das könnte ich zwar rausbekommen, aber nur ziemlich umständlich indem ich von jedem Prozess die PTs einblenden müssten (in den Kernel) und die PTs dann nach der Page durchsuchen müsste. Bis das alles fertig ist, kann die Page schonwieder in einem ganz anderem Prozess sein (zwecks Swapping).

Zitat von: svenska
Teile des physischen Adressraums sind nicht mit Speicher unterlegt, sondern mit Konfigurationsregistern der Hardware, meist jenseits des realen RAM-Ausbaus (z.B. jenseits der 2GB). Dort muss ein Treiber also unter Umständen physischen Adressraum in seinen eigenen virtuellen Adressraum mappen, der kein RAM ist.
Was du meinst ist linearer Adressraum und virtueller Adressraum! Physischer Speicher (wie der Name schon sagt) ist wirklich vorhandener RAM!
Und wenn du auf einem 32bit System 4GB RAM hast, dann belegt auch MMIO physischen RAM, was halt weniger schön, aber unvermeidbar ist.

Zitat von: svenska
Wo die Adressen im virtuellen Adressraum landen, ist egal. Welche Adressen im physischen Adressraum benutzt werden, hängt konkret von der Hardware ab (Konfigurationsregister sind fest) und ist nur teilweise programmierbar (Zieladresse des DMA ist es).
Da liegst du falsch. Denn die MMIO Adressen von PCI Geräten kann man sehr wohl selber bestimmen oder wie meinst du funktioniert das!? Eigentlich macht das BIOS diese Verwaltung, aber wenn es das nicht macht, müsstest du es selber machen und genau das ist momentan bei mir nicht möglich (da ich noch nichts habe, um bestimmte Pages im PMM als benutzt zu markieren).

Zitat von: svenska
Wie gesagt, Teile des physischen Adressraums, den du benötigst, sind nicht mit RAM unterlegt.
Wie oben geschrieben, stimmt das leider nicht immer.

Zitat von: svenska
Wenn der Treiber physisch 4 MB RAM unterhalb der 16 MB fordert (weil es halt ein popeliger ISA-SCSI-Controller ist), dann wird das wahrscheinlich nicht gehen. Wenn du aber gerne physisch 4 MB RAM als Block irgendwo möchtest, dann geht das wahrscheinlich schon. Ist der RAM voll, dann geht das eben nicht. Wie auch?
Deswegen macht es z.B. Linux auch so, dass so lange wie freier Speicher >16MB vorhanden ist, wird dieser genommen und somit kann der Speicher <16MB für ISA Treiber genutzt werden. Bei meinem Bsp darf das also nicht passieren.
Mir geht es auch nicht darum das der RAM voll ist, sondern das er fragmentiert ist!

Zitat von: svenska
Außerdem sollte der Treiber für die Kommunikation mit dem Gerät den Speicher direkt beantragen, oder zumindest einen kleinen Block (z.B. 64 KB). Damit garantierst du auch bei voller Speicherauslastung, dass du die Hardware ansteuern kannst.
Ich habe mir das für ISA Geräte so vorgestellt, das sie immer "nur" 64KB Speicher bekommen (davon wird es 8-10 Blöcke geben) und mit diesem Block dann auch auskommen müssen.

Aber die Idee kann ich auch auf andere Treiber übertragen. Problematisch wären dann aber Systeme mit wenig RAM (im Moment soll mein OS auch mit 8MB klar kommen), wo man nicht einfach mal sagenkann , ich benutze jetzt immer 4MB um die Daten von HDD in den Speicher zu bekommen und kopiere die Daten dann in SharedMem.
Was man machen könnte, ist je nach Speicherausstattung einen Cache bei der Initialisierung anzulegen.

Zitat von: svenska
Was nicht ausreicht, da der physische Adressraum halt 4GB groß ist und du dort (z.B. ab 3GB) den Framebuffer der Grafikkarte oder die PCI-Konfigurationsregister findest. Die musst du auch verwalten!
Im Moment gehe ich noch davon aus, dass das BIOS diese Arbeit für mich schon gemacht hat, aber ich werde mir wohl nochmal was einfallen lassen müssen wie ich es mache, wenn das nicht der Fall ist. Wobei hier dann auch die Frage aufkommt, wie bekomme ich raus, dass das BIOS die Arbeit schon gemacht hat?

Zitat von: svenska
Was hat dein Treiber davon, wenn er sich jede einzelne Page, die er für die Kommunikation mit der Hardware braucht, einzeln anfordern muss? Außerdem garantierst du ja nicht, dass die Pages zusammenhängend sind.
Der Treiber fordert ja nicht jede Page einzeln an, sondern er muss für jede Page einzeln nachgucken welche physische Adresse dahinter steckt und das genau wegen dem Grund, dass die Pages nicht zusammenhängend sein müssen (es bei der Initialisierung aber höchst wahrscheinlich sein werden).

Zitat von: svenska
Erklär du mal dem HDD-Controller, dass er die ersten 4 KB nach 0x3400 0000, die zweiten 4 KB nach 0x3800 0000 und die dritten 4 KB nach 0x3400 8000 schreiben soll. Das heißt, du programmierst die Hardware dreimal, um 12KB von der Festplatte zu lesen.
Im schlimmsten Fall, ja ;) Aber bevor es soweit kommt, würde ich halt sagen, der Treiber guckt wieviel RAM das System gesamt hat und legt sich danach einen Cache an (für DMA) und damit ist das Problem dann auch gegessen. Obwohl es gerade bei der HDD nicht die Welt sein sollte, für jede Page eine neue Anfrage zu machen, da ersten die Datei sowieso fragmentiert sein könnte (dann musst du das eh machen) und die Festplatte so "langsam" liest das sich an der absoluten Zeit nicht viel ändern wird.

Zitat von: svenska
Implementier lieber zwei Funktionen:

*getPhysMem( int size, ptr physAddr )
-> gib mir "size" Bytes ab physisch "physAddr" zurück
=> malloc() mit gegebener Adresse für deinen PMM

*getPhysMem( int size, ptr *physAddr )
-> gib mir "size" Bytes Speicher und schreibe in "physAddr" die physische Adresse rein
=> malloc() mit Rückgabe der verwendeten physischen Adresse
Also beide Funktionen haben schonmal das Problem (was aber auch nur meiner Sichtweise entspricht) das sie mit "Bytes" arbeiten, aber die Größe eigentlich auf 4KB Blöcke beschränkt ist.
Dann habe ich bei der ersten Funktion noch das Problem, versuche das mal bei einem PMM der mit nem Stack arbeitet!
Die 2. Funktion ist da schon eher was für mich, aber siehe weiter unten.

Zitat von: svenska
Wenn du willst, kannst du noch einen Alignment-Parameter mit einbinden, wenn du z.B. Hardware hast, die ein Alignment >4K braucht.
Gibt es sowas (also wo die Adresse wo das Gerät hinschreiben soll ein Alignment >4K brauch)? Das wäre ein echtes Problem :(

Zitat von: svenska
Was du dir sparst:
- Prozesse müssen die PageTables nicht selbst parsen können (Portabilität, vgl. taljeth)
- Prozesse haben keine Möglichkeit, das Mapping zwischen virt. und phys. Adressraum rauszukriegen (Sicherheit)
- nur ein Syscall pro Treiber und Adressraumblock
Was die Portabilität betrifft, siehe meine Antwort darauf und auch muss es der Treiber nicht selbst könne (siehe selbe Antwort).
Mir hat noch keiner eine wirkliche Antwort gegeben wo das Sicherheitsproblem wäre, wenn der Treiber die PTs parsen könnte.
Beim Parsen der PTs hätte ich auch nur einen Syscall.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 19:34
Zitat von: svenska
Du traust also dem Treiber zu, dass er nicht DMA auf "irgendwelchen" Speicher in die Hardware schreibt, traust ihm dann aber wieder nicht zu, dass er sich Speicher holen darf, den er braucht?
Naja, wenn du so ran gehst, dann brauchst du für einen Treiber gar keine Sicherheit! Wozu kontrollieren auf welche Ports der Treiber zugreifen darf?
Darum würde ich das auch komplett weglassen. Wichtig ist nur, dass keine Ressource von zwei Treibern angefordert wird, weil dann ist etwas faul. Wenn somit jede Hardware ihren Treiber hat, kann kein neuer Treiber mehr Unfug machen. Nicht elegant, aber besser als garnichts.

Mein Problem hier ist, meinst du damit auch, dass ich wissen müsste in welchem Prozess die Page 0x1000 ist? Denn das könnte ich zwar rausbekommen, aber nur ziemlich umständlich indem ich von jedem Prozess die PTs einblenden müssten (in den Kernel) und die PTs dann nach der Page durchsuchen müsste. Bis das alles fertig ist, kann die Page schonwieder in einem ganz anderem Prozess sein (zwecks Swapping).

Ich sehe den physischen Adressraum an dieser Stelle so, wie er auf dem Adressbus rausgeführt wird (wie die Hardware die Speicheradresse sieht) und den virtuellen Adressraum, wie ihn die Anwendung sieht. Welcher Treiber nun diesen physischen Speicherblock angefordert hat, dürfte dir relativ egal sein - da kümmert sich ja der Treiber selbst drum. Also bräuchtest du das nicht raussuchen.

Zitat von: svenska
Teile des physischen Adressraums sind nicht mit Speicher unterlegt, sondern mit Konfigurationsregistern der Hardware, meist jenseits des realen RAM-Ausbaus (z.B. jenseits der 2GB). Dort muss ein Treiber also unter Umständen physischen Adressraum in seinen eigenen virtuellen Adressraum mappen, der kein RAM ist.
Was du meinst ist linearer Adressraum und virtueller Adressraum! Physischer Speicher (wie der Name schon sagt) ist wirklich vorhandener RAM!
Und wenn du auf einem 32bit System 4GB RAM hast, dann belegt auch MMIO physischen RAM, was halt weniger schön, aber unvermeidbar ist.
Oh, das ist dann mein Fehler. Darum habe ich ja auch physischen Speicher (z.B. 2GB) von physischem Adressraum (immer 4GB) getrennt.

Zitat von: svenska
Wo die Adressen im virtuellen Adressraum landen, ist egal. Welche Adressen im physischen Adressraum benutzt werden, hängt konkret von der Hardware ab (Konfigurationsregister sind fest) und ist nur teilweise programmierbar (Zieladresse des DMA ist es).
Da liegst du falsch. Denn die MMIO Adressen von PCI Geräten kann man sehr wohl selber bestimmen oder wie meinst du funktioniert das!? Eigentlich macht das BIOS diese Verwaltung, aber wenn es das nicht macht, müsstest du es selber machen und genau das ist momentan bei mir nicht möglich (da ich noch nichts habe, um bestimmte Pages im PMM als benutzt zu markieren).

Also ist die Hardwareseite:
- das Gerät hat fixe Register bei 0xFFF08000-0xFFF0FFFF (findest du eher nicht auf dem PC)
- das Gerät hat konfigurierbare Register, die vom BIOS irgendwo hingelegt wurden, für dich also fix sind
- das Gerät hat konfigurierbare Register, deren Ort im linearen Adressraum du frei festlegen kannst
Was davon jetzt auf PCI zutrifft und was nicht, weiß ich nicht. Auf meinem ARM funktioniert der Framebuffer nach letzterem Prinzip. (Ich habe zwei Register bei 0x4D00 0014 und 0x4D00 0018, die die Position des Framebuffers im linearen Adressraum enthalten.)

Dein Treiber muss jetzt auf diese Register zugreifen können, also wird dieser Speicherbereich in den virtuellen Adressraum des Prozesses gemappt. Die virtuelle Adresse ist dabei egal. Konkret hast du deine virtuelle Adresse, die auf eine bekannte physische Speicheradresse zeigt. Und genau dieses Mapping muss deine Speicherverwaltung kennen. Welcher Prozess jetzt eine bestimmte physische Speicherseite hat, kann dir dabei egal sein.

Zitat von: svenska
Wie gesagt, Teile des physischen Adressraums, den du benötigst, sind nicht mit RAM unterlegt.
Wie oben geschrieben, stimmt das leider nicht immer.
Ich gehe von unter 4GB RAM auf einer 32-Bit-Maschine aus. Für den Fall, dass du 4GB RAM hast, wird er beim Lesen und Schreiben ohnehin ignoriert und ist nicht nutzbar. Bei aktivem PAE hast du wieder mehrere 4GB-Adressräume...

Mir geht es auch nicht darum das der RAM voll ist, sondern das er fragmentiert ist!
Wenn dein RAM physisch fragmentiert ist, hast du halt Pech. Darum legst du im Treiber ja auch bei der Initialisierung bereits deine Speicherblöcke an! Außerdem brauchst du für viele Geräte den Datenaustausch schon, um die Geräte initialisieren zu können.

Aber die Idee kann ich auch auf andere Treiber übertragen. Problematisch wären dann aber Systeme mit wenig RAM (im Moment soll mein OS auch mit 8MB klar kommen), wo man nicht einfach mal sagenkann , ich benutze jetzt immer 4MB um die Daten von HDD in den Speicher zu bekommen und kopiere die Daten dann in SharedMem.
Was man machen könnte, ist je nach Speicherausstattung einen Cache bei der Initialisierung anzulegen.
Wichtig ist, wie groß die Datenblöcke sind, die du bekommst und wieviel ein einzelner DMA-Transfer machen kann oder im Normalfall macht. Selbst bei 8MB RAM hast du 64K für die Festplatte übrig, wahrscheinlich sogar 512 KB. Das kannst du einmal in Abhängigkeit des RAMs ausrechnen lassen (64K bei <32MB, 1M bei <64MB und 4M sonst), außerdem kannst du das auch dynamisch anpassen - solange du einen physisch hinreichend großen freien Block hast. Das erledigst du dann aber im Treiber.

Zitat von: svenska
Was nicht ausreicht, da der physische Adressraum halt 4GB groß ist und du dort (z.B. ab 3GB) den Framebuffer der Grafikkarte oder die PCI-Konfigurationsregister findest. Die musst du auch verwalten!
Im Moment gehe ich noch davon aus, dass das BIOS diese Arbeit für mich schon gemacht hat, aber ich werde mir wohl nochmal was einfallen lassen müssen wie ich es mache, wenn das nicht der Fall ist. Wobei hier dann auch die Frage aufkommt, wie bekomme ich raus, dass das BIOS die Arbeit schon gemacht hat?
Ich kann mir irgendwie nicht vorstellen, dass dir das BIOS jeglichen Speicher, den eine Hardware benutzen mag, schon vorgekaut als Liste gibt... die Arbeit, sich die Adressräume einzuteilen, obliegt doch eigentlich dem Betriebssystem.

Zitat von: svenska
Was hat dein Treiber davon, wenn er sich jede einzelne Page, die er für die Kommunikation mit der Hardware braucht, einzeln anfordern muss? Außerdem garantierst du ja nicht, dass die Pages zusammenhängend sind.
Der Treiber fordert ja nicht jede Page einzeln an, sondern er muss für jede Page einzeln nachgucken welche physische Adresse dahinter steckt und das genau wegen dem Grund, dass die Pages nicht zusammenhängend sein müssen (es bei der Initialisierung aber höchst wahrscheinlich sein werden).
Dann gib eine Garantie vor. Macht die Treiberentwicklung wesentlich einfacher. Für Hardware willst du "RAM am Stück", alles andere ist sinnlos, von Scatter-Gather-Zugriffsmodi mal abgesehen, aber die haben andere Gründe.

Zitat von: svenska
Erklär du mal dem HDD-Controller, dass er die ersten 4 KB nach 0x3400 0000, die zweiten 4 KB nach 0x3800 0000 und die dritten 4 KB nach 0x3400 8000 schreiben soll. Das heißt, du programmierst die Hardware dreimal, um 12KB von der Festplatte zu lesen.
Im schlimmsten Fall, ja ;) Aber bevor es soweit kommt, würde ich halt sagen, der Treiber guckt wieviel RAM das System gesamt hat und legt sich danach einen Cache an (für DMA) und damit ist das Problem dann auch gegessen. Obwohl es gerade bei der HDD nicht die Welt sein sollte, für jede Page eine neue Anfrage zu machen, da ersten die Datei sowieso fragmentiert sein könnte (dann musst du das eh machen) und die Festplatte so "langsam" liest das sich an der absoluten Zeit nicht viel ändern wird.
Warum sollte der HDD-Treiber den gleichen RAM zweimal verbrauchen, nur weil du ihm keinen Block garantieren wolltest? In dem Moment hast du einen Cache am Stück und die Daten tauchen dann in 25 verschiedenen Speicherseiten auf und werden dorthin zusammengepopelt, ehe die Daten an deine Anwendung übergeben werden.

Zitat von: svenska
Implementier lieber zwei Funktionen:

*getPhysMem( int size, ptr physAddr )
-> gib mir "size" Bytes ab physisch "physAddr" zurück
=> malloc() mit gegebener Adresse für deinen PMM

*getPhysMem( int size, ptr *physAddr )
-> gib mir "size" Bytes Speicher und schreibe in "physAddr" die physische Adresse rein
=> malloc() mit Rückgabe der verwendeten physischen Adresse
Also beide Funktionen haben schonmal das Problem (was aber auch nur meiner Sichtweise entspricht) das sie mit "Bytes" arbeiten, aber die Größe eigentlich auf 4KB Blöcke beschränkt ist.
Spielt keine Rolle, dann rundest du eben auf die nächsten 4K auf. Du könntest ja auch Paging mit anderen Größen machen (z.B. 2K)

Dann habe ich bei der ersten Funktion noch das Problem, versuche das mal bei einem PMM der mit nem Stack arbeitet!
Das ist ein Program der Implementierung. Diese beiden Funktionen machen aber die Treiberentwicklung wesentlich einfacher.

Zitat von: svenska
Wenn du willst, kannst du noch einen Alignment-Parameter mit einbinden, wenn du z.B. Hardware hast, die ein Alignment >4K braucht.
Gibt es sowas (also wo die Adresse wo das Gerät hinschreiben soll ein Alignment >4K brauch)? Das wäre ein echtes Problem :(
Ich würde es nicht kategorisch ausschließen wollen. Im Härtefall hat der Gerätehersteller das Datenblatt des Chipherstellers falsch gelesen und eine Leitung zuwenig angeschlossen. Silicon Bugs sind manchmal echt tolle Dinger.

Mir hat noch keiner eine wirkliche Antwort gegeben wo das Sicherheitsproblem wäre, wenn der Treiber die PTs parsen könnte.
Beim Parsen der PTs hätte ich auch nur einen Syscall.
Was der Treiber nicht braucht, würde ich ihm auch nicht erzählen. Wenn der Treiber keine physischen/linearen Adressen kennt, die er nicht selbst für seine Arbeit braucht, dann kann er auch nicht versehentlich Schaden anrichten. Und da in meinem Ansatz der Treiber die physischen Adressen zugeteilt kriegt (es sei denn, er fordert sie selbst an - dann kennt er sie aber vorher schon und sie werden noch nicht benutzt)... der Netzwerktreiber muss nicht wissen, wo der HDD-Treiber die Sektoren hinspeichert. Was man mit dem Wissen machen kann, hatte ich oben schon geschrieben. Ist halt ne grundsätzliche Sache.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 19:55
Zitat von: svenska
Darum würde ich das auch komplett weglassen. Wichtig ist nur, dass keine Ressource von zwei  Treibern angefordert wird, weil dann ist etwas faul. Wenn somit jede Hardware ihren Treiber hat, kann kein neuer Treiber mehr Unfug machen. Nicht elegant, aber besser als garnichts.
Also entweder ganz oder gar nicht ;)

Wenn ich schon kontrolliere das solch Speicher nicht zweimal vergeben wird, dann kann ich auch kontrollieren (weil ich eh einmal dabei bin) an wenn er gegeben wird. Das selbe mach ich ja schon bei den IO-Ports.

Was ich eigentlich erreichen möchte ist, dass der Treiber ansich nur ein paar IO-Ports oder einen SharedMem-Bereich bekommt und ansonsten eigentlich gar nicht weiß wo das alles liegt.
Sprich am besten wäre es wenn der Treiber einfach immer bei Port 0 anfangen würde und man das ganze dann per Exception abfängt und den Port 0 auf den ersten Port des Gerätes "umleitet". Da dass aber zu kostspielig ist, mach ich es über die IO-Bitmap.
Was ich aber auf jeden Fall haben möchte ist, das nicht der Treiber entscheidet welche Ressourcen er gerne haben möchte, sondern das ich (Kernel oder Server, ist ansich egal) ihm sage, so die Ressourcen sind deine und an andere kommst du nicht ran.

Zitat von: svenska
Was davon jetzt auf PCI zutrifft und was nicht, weiß ich nicht.
Also soweit ich die PCI Specs verstanden (und gelesen) habe, sind weder die Adressen von MMIO (wo ich auch nen Framebuffer dazu zähle) noch die IO-Ports fixed, sondern können festgelegt werden (aber man muss sich an bestimmte Alignments halten).

Zitat von: svenska
Wenn dein RAM physisch fragmentiert ist, hast du halt Pech.
Sorry, aber mit der Einstellung kommst du nicht weit und genau dafür wurde ja Paging "erfunden", nur dass das bei DMA nicht funktioniert (bzw. kann ich mich erinnern, das es Geräte gibt wo du auch immer 4KB Blöcke reinschreibst und das Geräte dann die Daten da hinkopiert, so wird das Problem umgangen).

Zitat von: svenska
Ich kann mir irgendwie nicht vorstellen, dass dir das BIOS jeglichen Speicher, den eine Hardware benutzen mag, schon vorgekaut als Liste gibt... die Arbeit, sich die Adressräume einzuteilen, obliegt doch eigentlich dem Betriebssystem.
Da hast du mich falsch verstanden. Das BIOS legt die MMIOs und Framebuffers möglichst perfekt an das Ende des linearen Adressraumes. Ansonsten müsstest du alle PCI Geräte enumieren und anhand von ausprobieren (wieviele Ports, wie großer MMIO Raum) diesen Speicher/Ports festlegen und das ist nicht so einfach.

Zitat von: svenska
Warum sollte der HDD-Treiber den gleichen RAM zweimal verbrauchen, nur weil du ihm keinen Block garantieren wolltest? In dem Moment hast du einen Cache am Stück und die Daten tauchen dann in 25 verschiedenen Speicherseiten auf und werden dorthin zusammengepopelt, ehe die Daten an deine Anwendung übergeben werden.
Hier habe ich wieder gar nicht verstanden was du meinst bzw. was du von mir willst ;)

Zitat von: svenska
der Netzwerktreiber muss nicht wissen, wo der HDD-Treiber die Sektoren hinspeichert. Was man mit dem Wissen machen kann, hatte ich oben schon geschrieben. Ist halt ne grundsätzliche Sache.
Da ist irgendwie ein Fehler drin! Bei einem Mikrokernel ist jeder Treiber ein eigenständiger User-Prozess. Der Netzwerktreiber bekommt also gar nicht raus wo der HDD-Treiber seine Sektoren hinspeichert! Der Netzwerktreiber kann nur innerhalb seines Prozesses gucken welche physische Adresse zu einer virtuellen gehört.

Zitat von: svenska
Was man mit dem Wissen machen kann, hatte ich oben schon geschrieben. Ist halt ne grundsätzliche Sache.
Sprich wenn obiges Problem nicht besteht kann man das mit dem Parsen so machen?!

Mal was anderes, wie kommt es das du hier ein Sicherheitsproblem siehst, bei der Sache ob ein Treiber aber falschen Speicher mappt nicht?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 20:07
Was du meinst ist linearer Adressraum und virtueller Adressraum! Physischer Speicher (wie der Name schon sagt) ist wirklich vorhandener RAM!
Und wenn du auf einem 32bit System 4GB RAM hast, dann belegt auch MMIO physischen RAM, was halt weniger schön, aber unvermeidbar ist.
Moment, Moment, Moment... Wir benutzen hier x86-Terminologie, oder? Dann bitte mal das Intel-Manual Teil 3a, Kapitel 3.1 anschauen (Memory Management Overview).

Virtuelle Adressen sind das, was das Programm sieht und bestehen aus einem Segment und Offset. An dieser Stelle haben wir die erste Übersetzung. Nachdem die Segmentierung erledigt ist, landen wir bei linearen Adressen. Und diese linearen Adressen wiederum werden mit Paging auf physische Adressen abgebildet.

Svenska meint hier also wirklich den physischen Adressraum, nicht den linearen.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 20:18
Naja, da wir aber auch von Flat-Memory ausgehen/reden ist der lineare Adressraum = 4GB. In dem Fall kann man also rein theoretisch linear und physisch gleichwertig verwenden.

Bei meiner Erklärung ist es aber einfacher zwischen wirklich vorhandenem RAM und einfach nur dem Adressraum zu unterscheiden ;)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 20:42
Nein, mit Flat Memory ist virtuell und linear dasselbe.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 20:46
Jap, muss dir recht geben, macht auch mehr Sinn, denn die virtuellen Adressen sind linear = zusammenhängend, aber die physischen müssen es nicht sein.

Scheiß Haarspalterei ;)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 20:59
Dafür sind meine Beiträge wenigstens kürzer als Eriks. ;)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 21:14
*seufz*

Sagen wir es mal so, wenn dein Hardwaretreiber die Hardware wirklich ansprechen möchte - und da mag es durchaus sein, dass die zu verwendenden Ressourcen eben nicht frei programmierbar sind - dann muss der Treiber in der Lage sein, einen bestimmten physischen Bereich mappen zu können. Dass er das kann, unterscheidet ihn von einem Userspace-Prozess.

Angenommen, für jede Hardware gibt es einen Treiber, dann ist jeder von einer Hardware genutzter physischer Speicher durch irgendeinen Treiber belegt. Wenn du also auf Doppelbelegungen prüfst, dann kann der Treiber schonmal per se nicht auf fremde Hardwareressourcen zugreifen - also keine Sicherheitslücke.

Wenn aber jedes Programm (oder auch jeder Treiber) jederzeit nachschauen kann, wo im physischen Speicher irgendwelche Systemteile rumliegen, dann kann er diese auch überschreiben. Das ist wiederum eine Sicherheitslücke. Oder andersrum: Es gibt Exploits für Netzwerkkartentreiber (Angriff via Netzwerk, also von remote), um Code im Kernelmodus zur Ausführung zu bringen. Basiert aber darauf, dass der (gehackte) Netzwerkkartentreiber die physischen Adressen des Kernels kennt und per DMA überschreiben lässt. (Im speziellen Falle irgendwie 4-16 Bytes je nach Zusammensetzung des Pakets und daher recht umständlich, aber geht.) Das Mapping von physisch nach irgendwo ist also zuviel Information und wird ohnehin nicht gebraucht.

Die Ressourcen, die ein Treiber möchte, sollte man ihm schon geben können, wenn sie denn noch frei sind - denn der Treiber muss ja wissen, welche Ressourcen die Hardware nun gern hätte. Genau diese Information möchtest du aber dem Bussystem entnehmen. Ich glaube nicht, dass das in jedem Fall funktioniert. (Bspw. sind manche Hersteller dafür bekannt, im PCI-Konfigspace komisches Zeugs stehen zu haben, was da nicht unbedingt hingehört.) Andererseits gibt es wieder Silicon Bugs, um die der Treiber evtl. herumarbeiten muss.

Wenn dein RAM fragmentiert ist, hast du halt Pech. Die Einstellung bleibt. Du könntest ihn dann höchstens defragmentieren - da die physischen Adressen ja im Userspace nicht vorhanden sind, reicht ein bisschen MMU-Guruguru. Im Zweifelsfall machst du, wenn das nicht geht, dein DMA halt nur mit 4K-Blöcken oder PIO als Rückfallstrategie. Das Problem ist das gleiche, wie RAM voll mit nicht-auslagerungsfähigem Speicher. Da kann man irgendwann nichts mehr tun.

Dein Ansatz, bei fragmentiertem physischem Speicher einfach die DMA-Zugriffe zu verteilen und dann virtuell einen zusätzlichen linearen Cache anzulegen, bringt wenig. Die Anwendungen müssen die Daten ohnehin im Block kriegen, da ist es auch einfach sinnvoller, es gleich im physischen Block zu reservieren und das zu übergeben. Sparst du dir einmal das Kopieren der Daten. Alternative: Ich habe nicht verstanden, was du meintest.

Ich denke, die einfachste Variante ist es, in jedem Treiber eine Rückfallstrategie zu haben. Das kann PIO sein, das kann aber auch einfach eine minimale Blockgröße von 4K sein. Oder aber - bei nichtkritischen Treibern - geht es dann einfach nicht. Wenn deine Webcam die Daten in ein System pumpt, was eh schon soweit hinüber ist, dass nichts mehr so recht geht, dann wird das auch bröckchenweise nicht unbedingt besser. Außerdem musst du deine Speicherverwaltung schon hinreichend verkorkst haben, dass du physisch jede zweite Page belegt hast und die dazwischen nicht. Die Wahrscheinlichkeit geht gegen null - das ist das gleiche wie mit Deadlocks. Eine sinnvolle Strategie ist den Kopf in den Sand zu stecken und zu sagen "passiert nicht - und wenn doch: Pech". Dann muss der User halt mal was ändern.

@taljeth: Und meine. ;-)

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 06. September 2010, 21:29
Zitat von: svenska
Wenn aber jedes Programm (oder auch jeder Treiber) jederzeit nachschauen kann, wo im physischen  Speicher irgendwelche Systemteile rumliegen, dann kann er diese auch überschreiben. Das ist wiederum eine Sicherheitslücke. Oder andersrum: Es gibt Exploits für Netzwerkkartentreiber (Angriff via Netzwerk, also von remote), um Code im Kernelmodus zur Ausführung zu bringen. Basiert aber darauf, dass der (gehackte) Netzwerkkartentreiber die physischen Adressen des Kernels kennt und per DMA überschreiben lässt. (Im speziellen Falle irgendwie 4-16 Bytes je nach Zusammensetzung des Pakets und daher recht umständlich, aber geht.) Das Mapping von physisch nach irgendwo ist also zuviel Information und wird ohnehin nicht gebraucht.
Nur um dem nochmal was entgegen zu setzen ;)

Ich bi mir nicht sicher (und zu faul nachzugucken) ob ich es nicht schonmal erwähnt habe, aber ich würde dem Treiber nur gestatten die PTs zu parsen die den UserSpace betreffen. Somit kann er auch nicht in den KernelSpace gucken, aber das ist doch logisch!

Zitat von: svenska
Die Ressourcen, die ein Treiber möchte, sollte man ihm schon geben können, wenn sie denn noch frei sind - denn der Treiber muss ja wissen, welche Ressourcen die Hardware nun gern hätte. Genau diese Information möchtest du aber dem Bussystem entnehmen. Ich glaube nicht, dass das in jedem Fall funktioniert. (Bspw. sind manche Hersteller dafür bekannt, im PCI-Konfigspace komisches Zeugs stehen zu haben, was da nicht unbedingt hingehört.) Andererseits gibt es wieder Silicon Bugs, um die der Treiber evtl. herumarbeiten muss.
Also erstens, wenn er die Daten nicht aus dem PCI ConfigSpace bekommt wo soll er seine Adressen sonst herbekommen? Und das nächste Problem ist, was passiert wenn der Speicher den der Treiber (angeblich) will mit physischen RAM hinterlegt ist? Selbst wenn der Speicher gerade nicht in Benutzung ist, finde ich das doch eher problematisch.
Aber im Endeffekt ist es natürlich egal, selbst wenn man ihm die Ressourcen zuweist, kann er das System durch DMA zum Absturz bringen.

Zitat von: svenska
Dein Ansatz, bei fragmentiertem physischem Speicher einfach die DMA-Zugriffe zu verteilen und dann virtuell einen zusätzlichen linearen Cache anzulegen, bringt wenig. Die Anwendungen müssen die Daten ohnehin im Block kriegen, da ist es auch einfach sinnvoller, es gleich im physischen Block zu reservieren und das zu übergeben. Sparst du dir einmal das Kopieren der Daten. Alternative: Ich habe nicht verstanden, was du meintest.
Da hast du mich tatsächlich nicht verstanden. Ich meine das genau anders herum. Ich meinte das du einen Cache (mit zusammenhängendem Speicher) anlegst und dort per DMA reinschreiben lässt und dann in neuen (nicht zusammenhängenden Speicher) Speicher kopierst.
Aber wenn ich mir das Kopieren ersparen will (ich bin immernoch der Meinung dass das gerade beim Laden von langsamen optischen Speichern nicht wirklich was ausmacht) dann wird halt einfach in 4KB Blöcken geladen.

Zitat von: svenska
Außerdem musst du deine Speicherverwaltung schon hinreichend verkorkst haben, dass du physisch jede zweite Page belegt hast und die dazwischen nicht.
Wie kommst du darauf? Wenn du weißt wie ein Speichermanager funktioniert, dann kannst du die Situation bestimmt herbei führen. Ich sag mal so, so viel Speicher wie möglich anfordern und dann jede 2. Page wieder freigeben, sollte nicht das Problem sein und wenn das dann auch noch direkt nach dem Booten passiert, sollte die Wahrscheinlichkeit nicht schlecht sein, das du zusammenhängenden Speicher bekommst.

Zitat von: svenska
Dann muss der User halt mal was ändern.
Genau da liegt ja das Problem, der kann nichts ändern, das muss der Programmierer machen. Was willst du als User denn machen wenn irgendein Programmierer bei einem Treiber geschludert hat und dein System ständig zum Absturz bringt?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 06. September 2010, 22:27
Hallo,


Worüber streitet Ihr eigentlich?
Es gibt bei halbwegs moderner Hardware absolut keine Notwendigkeit physischen Speicher zusammenhängend zu allozieren! Heutzutage gibt es das Zauberwort "Scatter/Gather", das seit Jahren jeder Hersteller von irgendwelcher PCI-Hardware in die Prospekte schreibt (in letzter Zeit hat das wieder nachgelassen weil langsam alle wissen dass das jeder kann).

LAN-Controller, USB-Host-Controller und AHCI-Controller können die Daten in kleinen, verteilten und unausgerichteten Häppchen quer über den RAM völlig problemlos zusammensuchen. Für Floppy-Controller, die auf einen ISA-DMA-Mechanismus angewiesen sind (der älter ist als ich), gilt das leider nicht aber ansonsten sehe ich da keine Probleme. Die überwiegende Mehrheit der Hardware kann sogar mit 64 Bit-Adressen umgehen so das es eigentlich keine Notwendigkeit gibt zur Kommunikation mit der Hardware bestimmte physische Speicherbereiche zu benutzen. Für Floppys, als einzige Ausnahme die (in noch nicht ganz verrosteten PCs) überhaupt noch existiert, könnte man ja beim booten einen Zwischenpuffer in den ersten 16MByte reservieren (64kBytes sollten reichen) der dann vom Treiber benutzt wird um darin die ISA-DMA-Aktivitäten zu fahren und die Daten händisch umzukopieren. Alle andere Hardware kann direkt mit den physischen Pages der User-Mode-Programme arbeiten, egal wie zerstreut die auch sind.


Virtuelle Adressen sind das, was das Programm sieht und bestehen aus einem Segment und Offset. An dieser Stelle haben wir die erste Übersetzung. Nachdem die Segmentierung erledigt ist, landen wir bei linearen Adressen. Und diese linearen Adressen wiederum werden mit Paging auf physische Adressen abgebildet.
mit Flat Memory ist virtuell und linear dasselbe.
Fürs Protokoll, beide Aussage sind absolut korrekt. Jegliche Form von Zweifel ist verboten!


Dafür sind meine Beiträge wenigstens kürzer als Eriks. ;)
Was soll denn das Bitte heißen?


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Programm Noob am 06. September 2010, 22:34
Erik deine Beiträge sind leider sehr lang sind dafür aber auch sehr leicht zu verstehen. Das gleiche gilt übrigens auch für die Beträge von Flashburn.

Programm Noob
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 06. September 2010, 22:53
Dafür sind meine Beiträge wenigstens kürzer als Eriks. ;)
Was soll denn das Bitte heißen?
Im Zweifelsfall, dass ich tippfaul bin. :)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 06. September 2010, 23:42
Also erstens, wenn er die Daten nicht aus dem PCI ConfigSpace bekommt wo soll er seine Adressen sonst herbekommen? Und das nächste Problem ist, was passiert wenn der Speicher den der Treiber (angeblich) will mit physischen RAM hinterlegt ist? Selbst wenn der Speicher gerade nicht in Benutzung ist, finde ich das doch eher problematisch.
Wenn der Treiber Bereiche mit physischem RAM will, dann will er die vielleicht, um Daten auszutauschen. Und wenn er die Daten nicht aus dem PCI ConfigSpace bekommt, dann vielleicht aus der Dokumentation des Prozessors (z.B. Samsung S3C2410) - tut mir Leid, wenn ich darauf rumhacke, aber ich denke halt bissl weiter als nur PC-Plattform. Die finde ich inzwischen komplett überholt, mitsamt x86...

Aber im Endeffekt ist es natürlich egal, selbst wenn man ihm die Ressourcen zuweist, kann er das System durch DMA zum Absturz bringen.
Ja, aber gezielte Codeausführung durch Bugs/Angriffe im Kernel wird dadurch erschwert.

Da hast du mich tatsächlich nicht verstanden. Ich meine das genau anders herum. Ich meinte das du einen Cache (mit zusammenhängendem Speicher) anlegst und dort per DMA reinschreiben lässt und dann in neuen (nicht zusammenhängenden Speicher) Speicher kopierst.
Das ist doch der physisch zusammenhängende Speicherblock. Davon rede ich die ganze Zeit. ;-)

Zitat von: svenska
Außerdem musst du deine Speicherverwaltung schon hinreichend verkorkst haben, dass du physisch jede zweite Page belegt hast und die dazwischen nicht.
Wie kommst du darauf? Wenn du weißt wie ein Speichermanager funktioniert, dann kannst du die Situation bestimmt herbei führen. Ich sag mal so, so viel Speicher wie möglich anfordern und dann jede 2. Page wieder freigeben, sollte nicht das Problem sein und wenn das dann auch noch direkt nach dem Booten passiert, sollte die Wahrscheinlichkeit nicht schlecht sein, das du zusammenhängenden Speicher bekommst.
Es geht hier nicht um Speicher - es geht um physischen Speicher. Auf den hat eine Anwendung keinen Einfluss und auch keinen Zugriff, sollte im Normalfall nichtmal in der Lage sein, solche Adressen zu erhalten! Treiber sollten hingegen mit entsprechenden Privilegien ausgestattet sein, sodaß diese mit höherer Wahrscheinlichkeit eben nicht mit den getPhysMem-Funktionen spielen.

Als Anwendung den physischen Speichermanager so durcheinander bringen sollte nicht (oder nur sehr schwer) möglich sein.

Zitat von: svenska
Dann muss der User halt mal was ändern.
Genau da liegt ja das Problem, der kann nichts ändern, das muss der Programmierer machen. Was willst du als User denn machen wenn irgendein Programmierer bei einem Treiber geschludert hat und dein System ständig zum Absturz bringt?
Neues Gerät kaufen? Ist doch bei Windows genauso. Noch nie irgendwelche kaputten Treiber gehabt? Ich denke da an diverse DVB-C-Karten, die unter verschiedensten Umständen segfaulen/bluescreenen.

Außerdem ging es nicht um Systemabsturz durch geschluderte Treiber. Ich meinte an der Stelle, dass, wenn jede physische zweite Speicherseite belegt ist - aus welchen Gründen auch immer - der User halt mal ein paar Anwendungen schließen muss. Ich behaupte, dass menschenverstandsgeschriebene Treiber nicht solche verkorksten Dinge tun. Die sollen die Hardware ansteuern und ne API bereitstellen und mehr nicht.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 07. September 2010, 11:20
Zitat von: svenska
Und wenn er die Daten nicht aus dem PCI ConfigSpace bekommt, dann vielleicht aus der Dokumentation des Prozessors (z.B. Samsung S3C2410)
Wenn der die Daten nicht von dort bekommt, dann kannst du das Gerät wegwerfen ;) Denn du wirst dann keine Probleme haben einen PC zu finden der mit diesem Gerät nicht funktioniert. Bei PCI Geräten sollten fixe Adressen eigentlich Vergangenheit sein.

Zitat von: svenska
- tut mir Leid, wenn ich darauf rumhacke, aber ich denke halt bissl weiter als nur PC-Plattform. Die finde ich inzwischen komplett überholt, mitsamt x86...
Sorry, wenn ich das mal so sage, wird von Assembler auch schon seit Jahrzenten behauptet und es wird immernoch benutzt. Dazu kommt, das wir hier (wenn nicht extra genannt) von x86 ausgehen.

Zitat von: svenska
Es geht hier nicht um Speicher - es geht um physischen Speicher. Auf den hat eine Anwendung keinen Einfluss und auch keinen Zugriff, sollte im Normalfall nichtmal in der Lage sein, solche Adressen zu erhalten! Treiber sollten hingegen mit entsprechenden Privilegien ausgestattet sein, sodaß diese mit höherer Wahrscheinlichkeit eben nicht mit den getPhysMem-Funktionen spielen.
Du willst mir also erzählen das dein PMM irgendwelche zufällig ausgewählten Seiten herausgibt? Wenn auf meinen OS nur eine Anwendung läuft und so viel wie möglich Speicher anfordert, dann kannst du davon ausgehen, das der so ziemlich zusamenhängend rausgegeben wird und das ist kein Bug, das ist nunmal so, kurz nach dem Start.

Zitat von: svenska
Ich meinte an der Stelle, dass, wenn jede physische zweite Speicherseite belegt ist - aus welchen Gründen auch immer - der User halt mal ein paar Anwendungen schließen muss.
Genau da wiederspreche ich dir ;) Es kann doch nicht sein, das wenn ich 1GB RAM frei habe, dass ich ne Meldung bekomme "nicht genügend Speicher". Da läuft dann wirklich was schief!

Zitat von: erik
Es gibt bei halbwegs moderner Hardware absolut keine Notwendigkeit physischen Speicher zusammenhängend zu allozieren! Heutzutage gibt es das Zauberwort "Scatter/Gather", das seit Jahren jeder Hersteller von irgendwelcher PCI-Hardware in die Prospekte schreibt (in letzter Zeit hat das wieder nachgelassen weil langsam alle wissen dass das jeder kann).
Auf der einen Seite gut, nur blöd das ich auch alte Hardware unterstütze ;)

Also um es festzuhalten, zusammenhängenden physischen Speicher braucht man nicht unbedingt.

Und ich gehe mal davon aus, wenn der Treiber nur die PTs von seinem UserSpace sieht, sollte das auch kein Problem darstellen!?

Edit::

Zitat von: svenska
tut mir Leid, wenn ich darauf rumhacke, aber ich denke halt bissl weiter als nur PC-Plattform. Die finde ich inzwischen komplett überholt, mitsamt x86...
Was mir noch eingefallen ist, ich denke du denkst noch zu sehr "Linux" ;)

Wenn du von festen Adressen ausgehst, die der Treiber entweder durch ausprobieren rausbekommt oder die man beim Kompilieren festgelegt hat, was bringt dir das?
Als Bsp. mal die ganzen ARM-Boards, es ist immer die selbe CPU und viele zusätzliche Geräte sind auch gleich, aber die MMIO Adressen sind anders, d.h. bei Linux, für jedes Board muss der Kernel/Treiber neu komiliert werden, nur weil ein paar andere Geräte und ein paar andere Adressen vorhanden sind?! Was bitte soll das, das ist in meinen Augen unfug und alles anders als modern!
Ich habe meinen Device-Server auch im Hinblick auf solche ARM-Boards geplant, nämlich das der Treiber die Ressourcen zugewiesen bekommt. Was ich damit erreichen möchte ist, dass du für jedes neue Board nicht den Kernel oder den Treiber neu kompilieren musst, sondern das du einfach nur ein Skript änderst wo alle Geräte und Adressen (für das jeweilige Board) drin stehen. So kann ich einfach mein OS nehmen, ohne es neu kompilieren zu müssen und kann durch ne kleine Änderung an einem Skript mein OS auf nem neuen Board lauffähig machen. Das nenn ich vernünftig, modern und im Hinblick auf andere Architekturen entwickelt!
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 07. September 2010, 19:41
Bei PCI Geräten sollten fixe Adressen eigentlich Vergangenheit sein.
Bei PCI-Geräten.

Zitat von: svenska
Ich meinte an der Stelle, dass, wenn jede physische zweite Speicherseite belegt ist - aus welchen Gründen auch immer - der User halt mal ein paar Anwendungen schließen muss.
Genau da wiederspreche ich dir ;) Es kann doch nicht sein, das wenn ich 1GB RAM frei habe, dass ich ne Meldung bekomme "nicht genügend Speicher". Da läuft dann wirklich was schief!
Ich will dich sehen, wie du es in einer Anwendung (nicht Treiber!) hinkriegst, jede zweite physische Speicherseite zu belegen. Im virtuellen Adressraum spielt das schließlich überhaupt keine Rolle.

Also um es festzuhalten, zusammenhängenden physischen Speicher braucht man nicht unbedingt.
Wenn du damit zufrieden bist, dass du damit keine DMA-Zugriffe jenseits der 4K mehr garantieren kannst, dann stimmt das. Ich behaupte, es gibt Hardware, die größere DMA-Zugriffe braucht. (Und sei es die Netzwerkkarte, die einen 8K Jumbo-Frame wegspeichern will.)

Aber du magst mir nicht glauben.

Wenn du von festen Adressen ausgehst, die der Treiber entweder durch ausprobieren rausbekommt oder die man beim Kompilieren festgelegt hat, was bringt dir das?
Es gibt nunmal Geräte mit festen Adressen. Dazu gehören ISA-Geräte, aber auch CPU-interne Geräte. Fertig.

Als Bsp. mal die ganzen ARM-Boards, es ist immer die selbe CPU und viele zusätzliche Geräte sind auch gleich, aber die MMIO Adressen sind anders, d.h. bei Linux, für jedes Board muss der Kernel/Treiber neu komiliert werden, nur weil ein paar andere Geräte und ein paar andere Adressen vorhanden sind?! Was bitte soll das, das ist in meinen Augen unfug und alles anders als modern!
Wenn man jetzt die ganzen Bussysteme abstrahiert (und ich sehe MMIOs nunmal als Bussystem), dann kannst du das auch komplett dynamisch machen. Der Kernel bootet, sieht "oh, ich laufe auf einem Quanta IL1, also finde ich ab Adresse 0xblubber die GPIOs für das WLAN" und bindest das halt dynamisch an den Treiber an.

Was du prinzipiell vergisst, ist, dass du bei Geräten mit Spezialzweck (z.B. Navis) nur eine Serie hast, die du zuschneiden kannst. Das Problem ist bei MIPS noch viel schlimmer, aber grundsätzlich musst du manchmal proben (oder dich auf Tabellen verlassen), eben weil nicht jedes Bussystem auch einen Devicetree erzeugen kann!

Ich habe meinen Device-Server auch im Hinblick auf solche ARM-Boards geplant, nämlich das der Treiber die Ressourcen zugewiesen bekommt.
Ist ja auch vernünftig, zumindest für den Teil, der ohnehin fix (z.B. vom Bussystem her) ist.
Der Buffer für Netzwerkkarten ist jedoch dem System nicht unbedingt bekannt und/oder unterliegt Restriktionen der Hardware und/oder kann bei mehr RAM größer & effizienter gestaltet werden. Diese Entscheidung kann dein Device-Server nicht für jede Hardware optimal treffen, da er ja die Hardware nicht kennt. Er kennt höchstens das, was das Bussystem weiß.

Der Treiber weiß mehr. Und kann die Hardware an irgendwelche Begrenzungen anpassen.

Was ich damit erreichen möchte ist, dass du für jedes neue Board nicht den Kernel oder den Treiber neu kompilieren musst, sondern das du einfach nur ein Skript änderst wo alle Geräte und Adressen (für das jeweilige Board) drin stehen.
Also abstrahierst du das Bussystem. Einfache Systeme kennen keine Devicetrees, also musst du in der Lage sein, einen Treiber auch nachträglich zu laden - und ihm mitzugeben, wo er das Gerät findet. Solche Geräte, die nicht bereits initialisiert wurden (das betrifft beim PC z.B. auch sekundäre Grafikkarten, die nicht gebootet wurden!), müssen vom Treiber initialisiert werden - nicht vom Device-Server - und das betrifft insbesondere auch die Datenkommunikation mit dem Gerät.

So kann ich einfach mein OS nehmen, ohne es neu kompilieren zu müssen und kann durch ne kleine Änderung an einem Skript mein OS auf nem neuen Board lauffähig machen. Das nenn ich vernünftig, modern und im Hinblick auf andere Architekturen entwickelt!
Guck dir mal NetBSD an. Dort kannst du sämtliche Ressourcen im Bootloader angeben, sofern sie fix sind, und alles, was sich dynamisch ermitteln lässt, wird ermittelt. Und man kann dynamisch Geräte an Busse binden.

Warum ich mit Linux vergleiche, ist, dass ich Linux teilweise auf anderen Architekturen begutachte, wenn auch nicht viel, und weil Linux nunmal mehr Embedded-Bussysteme abstrahiert, wenn auch bei weitem nicht so schön wie NetBSD. Letztere kommen einfach nicht hinterher, so meine Einschätzung.

Aber ich schreibe wahrscheinlich eh gegen ne Wand.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 07. September 2010, 20:15
Zitat von: svenska
Ich will dich sehen, wie du es in einer Anwendung (nicht Treiber!) hinkriegst, jede zweite physische Speicherseite zu belegen. Im virtuellen Adressraum spielt das schließlich überhaupt keine Rolle.
Hab ich dir doch geschrieben, wenn du bei meinem (ich weiß nicht wie das andere OSs machen) als Anwendung direkt nach dem Booten, wo der Speicher noch nicht fragmentiert ist, den ganzen physischen Speicher mappst. Dann kannst du davon ausgehen, das ein Großteil davon zusammenhängend ist. Einfach weil der PMM den Speicher so rausgibt. Ich suche ja die erste freie Page und wenn du aufeinanderfolgend dann ist der Speicher der rausgegeben wird halt zusammenhängend.

Zitat von: svenska
Wenn du damit zufrieden bist, dass du damit keine DMA-Zugriffe jenseits der 4K mehr garantieren kannst, dann stimmt das. Ich behaupte, es gibt Hardware, die größere DMA-Zugriffe braucht. (Und sei es die Netzwerkkarte, die einen 8K Jumbo-Frame wegspeichern will.)
Ich habe ja auch geschrieben "nicht unbedingt". Soll heißen, wenn ein Treiber das unbedingt benötigt, muss er sich bei der Initialisierung einen Cache anlegen der die Bedingungen erfüllt.

Zitat von: svenska
Aber du magst mir nicht glauben.
Ich sags mal so, ich lasse mich gerne eines besseren belehren, aber dann möchte ich das auch schwarz auf weiß ;)

Zitat von: svenska
Es gibt nunmal Geräte mit festen Adressen. Dazu gehören ISA-Geräte, aber auch CPU-interne Geräte. Fertig.
Ich bin mir jetzt nicht sicher, aber gab es MMIO schon zu ISA Zeiten? Das einzige was da war, war doch das "Loch" zw. 15MB und 16MB oder?
Selbst wenn, dann kann ich da doch trotzdem in ein Skript eintragen und dem Treiber zuweisen.

Zitat von: svenska
Was du prinzipiell vergisst, ist, dass du bei Geräten mit Spezialzweck (z.B. Navis) nur eine Serie hast, die du zuschneiden kannst. Das Problem ist bei MIPS noch viel schlimmer, aber grundsätzlich musst du manchmal proben (oder dich auf Tabellen verlassen), eben weil nicht jedes Bussystem auch einen Devicetree erzeugen kann!
Ich kann dir nur das gleiche sagen, was ich auch schonmal erik gesagt habe, ich (und ich denke die Mehrheit der Anderen auch) schreibe ein "normales" (á la Windows/Haiku) OS und kein OS für irgendwelche Spezialhardware (wie z.B. ein Navi) und dann kommt noch hinzu das ich mich fürs erste auf die (veraltete) x86 Architektur beschränke und selbst wenn es mal soweit kommen sollte, wird wahrscheinlich "nur" ARM hinzukommen.
Selbst dann lässt sich das wunderbar mit einem Skript lösen und den Devicetree brauch ich doch gar nicht, genau deswegen will ich doch ein Skript haben.

Zitat von: svenska
Der Buffer für Netzwerkkarten ist jedoch dem System nicht unbedingt bekannt und/oder unterliegt Restriktionen der Hardware und/oder kann bei mehr RAM größer & effizienter gestaltet werden.
Hier würde ich halt auch gerne mal ne Quelle, wie eine Dokumentations sehen wollen. Denn an und für sich, müssten alle (und ich meine wirklich alle) vom Gerät verwendeten Ressourcen im PCI-ConfigSpace (ISA ist mal außen vor) stehen.
Ich habe mich mit Netzwerktreibern noch nicht wirklich beschäftigt, aber hat die Netzwerkkarte wirklich einen Buffer, den sie selbst zur Verfügung stellt und der nicht im PCI-ConfigSpace steht?

Zitat von: svenska
Also abstrahierst du das Bussystem. Einfache Systeme kennen keine Devicetrees, also musst du in der Lage sein, einen Treiber auch nachträglich zu laden - und ihm mitzugeben, wo er das Gerät findet. Solche Geräte, die nicht bereits initialisiert wurden (das betrifft beim PC z.B. auch sekundäre Grafikkarten, die nicht gebootet wurden!), müssen vom Treiber initialisiert werden - nicht vom Device-Server - und das betrifft insbesondere auch die Datenkommunikation mit dem Gerät.
Kann sein das ich hier einfach noch mit Unwissenheit glänze, aber sollte (um dein Bsp. aufzugreifen) nicht die 2. Graka auch bei der PCI Enumeration gefunden werden und somit sind ihre Ressourcen bekannt? Zumal was hat das Initialisieren mit den Ressourcen zu tun?

Ich gehe jetzt davon aus, das man entweder eine Möglichkeit hat, alle Geräte dynamisch zu "parsen" oder das alle Geräte, samt Ressourcen, vorher bekannt sind.
Wenn ich diese beiden Möglichkeiten betrachte reicht meine Skript Variante vollkommen aus. Selbst wenn der Treiber erst nachgucken (also proben) müsste ob ein Gerät vorhanden ist, dann könnte man diesen (den Treiber) mit allen möglichen Ressourcen doch in dem Skript eintragen.

Zitat von: svenska
Aber ich schreibe wahrscheinlich eh gegen ne Wand.
Wenn deine Argumente überzeugend sind, dann nicht ;)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 07. September 2010, 20:58
Hallo,


Also um es festzuhalten, zusammenhängenden physischen Speicher braucht man nicht unbedingt.
Genau!


Ich behaupte, es gibt Hardware, die größere DMA-Zugriffe braucht. (Und sei es die Netzwerkkarte, die einen 8K Jumbo-Frame wegspeichern will.)
Sehr viele Hardware benötigt größere Puffer aber die müssen eben nicht an einem Stück im physischen Speicher liegen. Ein Netzwerkkarte die wirklich Jumbo-Frames kann kann garantiert auch "Scatter/Gather", das heißt das empfangene Ethernet-Frame kann in einem aber auch in sehr vielen und sehr verteilten und unterschiedlich großen Häppchen über den physischen Speicher verstreut sein. Wer das nicht glaubt sollte sich mal die Datenblätter handelsüblicher Ethernet-Controller der letzten 15 Jahre ansehen. Oder die AHCI-Spezifikation und die EHCI-Spezifikation lesen. Keine dieser Hardware-Komponenten benötigt die Puffer (aus denen die Nutzdaten gelesen oder geschrieben werden) an einem Stück. Ein 512 Byte Sektor für ne Platte kann der AHCI-Controller auch in unausgerichteten 3 Byte Häppchen zusammensuchen (dass das nicht gerade performant ist ist jetzt mal unerheblich). Die Hardware-Entwickler wissen schließlich das übliche OSe Flat-Memory mit Paging benutzen und berücksichtigen das in ihrer Hardware.


aber hat die Netzwerkkarte wirklich einen Buffer, den sie selbst zur Verfügung stellt und der nicht im PCI-ConfigSpace steht?
Nein, der Puffer den der Netzwerk-Controller intern hat ist entweder selbst verwaltet (simpler FIFO) und nicht nach außen sichtbar (und ihm kann demzufolge auch nicht per BAR eine physische Adresse zugewiesen werden) oder er wird von der SW verwaltet und ist von außen sichtbar (und dann muss er auch per BAR eingerichtet werden können). Heutige PCI(-Express) Netzwerk-Controller fallen in die erste Kategorie, ist in den Datenblättern nachzulesen.

aber sollte (um dein Bsp. aufzugreifen) nicht die 2. Graka auch bei der PCI Enumeration gefunden werden und somit sind ihre Ressourcen bekannt?
Auf einem üblichen PC sollte das BIOS jeder PCI-Hardware die gewünschten Ressourcen zuweisen.

Zumal was hat das Initialisieren mit den Ressourcen zu tun?
Erst mal nichts, die Ressourcen werden vom BIOS zugewiesen und initialisiert wird das Gerät später vom Treiber (wenn das OS diesen lädt). Extra deswegen hat man den standardisierten Config-Space erfunden damit ein generisches BIOS auch einem ihm völlig unbekannten Gerät passende Ressourcen zuweisen kann und dieses Gerät somit von seinem Treiber initialisiert werden kann ohne das dieser sich um die Ressourcen-Zuweisung kümmern muss.

Ich gehe jetzt davon aus, das man entweder eine Möglichkeit hat, alle Geräte dynamisch zu "parsen" oder das alle Geräte, samt Ressourcen, vorher bekannt sind.
Ich denke mal das sollte auf jede Hardware zutreffen, was anderes kann ich mir jedenfalls nicht vorstellen (proben ist eigentlich ausgestorben).


Grüße
Erik


PS.: Ihr streitet Euch um nichts!
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 08. September 2010, 10:08
Zitat von: erik
PS.: Ihr streitet Euch um nichts!
Bis einer weint ;)

Zitat von: erik
die Ressourcen werden vom BIOS zugewiesen
Jein! Du kannst das im BIOS auch ausstellen (die Option heißt meistens "is a Plug&Play OS available") und dann müsste das vom OS gemacht werden, aber das wäre wirklich schlecht. Denn das würde einige Schwierigkeiten bedeuten (aber erst wenn soviel RAM vorhanden ist, das welcher davon von MMIO benutzt werden muss).

Was das "Proben" betrifft, wird von meinem OS dann einfach nicht unterstützt (ein paar Altlasten kann ich schon über Bord werfen).

Was mir aber noch nicht beantwortet wurde, gab es schon zu ISA Zeiten MMIO? War dafür nicht die Lücke im RAM zw 15MB und 16MB?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 08. September 2010, 10:41
Hallo,


Jein! Du kannst das im BIOS auch ausstellen (die Option heißt meistens "is a Plug&Play OS available") und dann müsste das vom OS gemacht werden
Ich hätte gedacht das dies nur die ISA-PnP-Karten betrifft. Da das BIOS auf jeden Fall den HDD-Controller und die Graphikkarte in betrieb nehmen muss (und auch noch USB und ne reihe anderes Zeug) muss es eigentlich die Ressourcen-Zuweisung eh erledigen, die kann man nämlich nicht in mehreren Etappen ausführen (wegen den Bridges u.ä.). Ich persönlich hab es jedenfalls noch nie erlebt dass das BIOS nicht jeder (funktionierenden) PCI-Karte die Ressourcen zugewiesen hätte. Das einzigste was das OS später noch mal ändern kann sind die IRQ-Zuweisungen, wenn z.B. in den APIC-Mode gewechselt wird und mehr IRQs zur Verfügung stehen.

Was das "Proben" betrifft, wird von meinem OS dann einfach nicht unterstützt (ein paar Altlasten kann ich schon über Bord werfen).
Proben war mal zu ISA-Zeiten, wo man die Karten noch mit Jumpern auf ihre I/O-Ports konfiguriert hat, üblich ist aber seit vielen Jahren ausgestorben. Du machst ganz sicher keinen Fehler wenn Dein OS sowas nicht unterstützt.

Was mir aber noch nicht beantwortet wurde, gab es schon zu ISA Zeiten MMIO? War dafür nicht die Lücke im RAM zw 15MB und 16MB?
Ja es gab bereits zu ISA-Zeiten MMIO, was glaubst Du was an 0xA0000 oder 0xB8000 liegt. Es gab auch mal Karten die EMS in Hardware zur Verfügung gestellt haben (die hatten 1 oder 2 MB RAM drauf und konnten davon 4 beliebige 16 kByte Häppchen in ein 64 kByte Fenster einblenden, dieses Fenster lag irgendwo zwischen 0xC8000 und 0xF0000). Ansonsten kann ich mich aber nicht an eine konkrete Verwendung von MMIO bei ISA erinnern (wahrscheinlich bin ich dafür einfach nicht alt genug ;) ), was natürlich nicht heißen soll das es das nicht gab schließlich muss ja diese Lücke von 15MB bis 16 MB irgendeinem Zweck gedient haben. Das große Problem mit ISA war eher das es nur einen sehr kleinen Speicher-Adressraum unterstützte (1 MB bei den kurzen Slots und 16 MB bei den langen Slots), da war nur selten viel Platz übrig um da wirklich sinnvolle Dinge rein zu legen.


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 08. September 2010, 13:39
Die BIOS-Einstellung "Plug'n'Play OS" gibt an, ob das BIOS jeder Hardware (disabled) die Ressourcen zuweisen soll oder nur der zum Booten benötigten Hardware (enabled). Das heißt konkret Grafik, HDD und (bei USB Legacy Enabled = true) den zum Booten benötigten USB-Geräten.

Zumindest war so die Ursprungsbedeutung. Ob die BIOSse das auch immer so machen, weiß ich nicht. Die Einstellung hat auf jeden Fall nichts mit ISAPnP zu tun, denn das ist immer eine Softwaregeschichte. Für Boot-Geräte (die eigentlich nie ISAPnP waren) ließ sich das auch im DOS-Programm abschalten und dort wurden dann fixe Ressourcen vergeben.

MMIO-Bereich ist wie gesagt der Bereich 640K-1M, sowie 15M-16M. Da der Platz allerdings dort recht klein ist, wurde das nicht von jeder Hardware unterstützt, meist irgendwelche Server-SCSI-Controller.

Scatter/Gather ist bei Netzwerkkarten eher vorgesehen, dass der Kernel den Header zusammenpopelt und dann im selben Paket die Nutzdaten aus dem Userspace hinterherschieben lässt, ohne die Daten in einen gemeinsamen Puffer kopieren zu müssen. Das ist eher nicht vorgesehen, dass der PMM so schlecht verwaltet wird, dass man die Pakete noch weiter splitten muss. Aber ich möchte nicht weiterstreiten.

Gruß
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 08. September 2010, 15:35
Hallo,


Die BIOS-Einstellung "Plug'n'Play OS" gibt an, ob das BIOS jeder Hardware (disabled) die Ressourcen zuweisen soll oder nur der zum Booten benötigten Hardware (enabled). Das heißt konkret Grafik, HDD
Das ist Quatsch! Man kann nicht nur einem Teil der PCI-Geräte die benötigten Ressourcen zuweisen und den Rest übergehen, dann hat man nämlich ein Problem wenn man den restlichen PCI-Geräten die gewünschten Ressourcen zuweisen will. Stell Dir mal vor hinter einer PCI-2-PCI-Bridge hängt ein HDD-Controller und ne Reihe anderes Zeugs (das ist absolut üblich, auch schon zu Zeiten des Pentium 1), wenn man nur dem HDD-Controller die Ressourcen zuweist und eine entsprechende Weiterleitung in der Bridge konfiguriert dann kann man den restlichen Geräten hinter dieser Bridge keine Ressourcen mehr zuweisen ohne die Weiterleitung zu ändern und wenn man die Weiterleitung ändert dann entstehen Kollisionen mit anderen Ressourcen/Weiterleitungen. Natürlich könnte das OS die Ressourcenzuweisung noch mal komplett von neuem durchführen aber dann würden sich einige Adressen ändern (von bereits zugewiesenen Ressourcen) und das dürfte unangenehme Nebenwirkungen haben (vor allem weil es sich ja um wichtige Boot-Geräte handelt). Schon um jedem PCI-Gerät die richtige PCI-Geräte-Adresse, also Bus/Device/Function, zuzuweisen muss man den gesamten PCI komplett traversieren (durch alle Bridges hindurch). Die PCI-Enumeration in mehreren Teilschritten zu erledigen ist einfach nicht vorgesehen (würde ja auch keinen Sinn ergeben).

<klug-scheiß-modus>
und (bei USB Legacy Enabled = true) den zum Booten benötigten USB-Geräten.
USB-Geräte bekommen keine Ressourcen wie Speicher, I/O-Ports oder IRQs, das bekommen nur die USB-Host-Controller. USB-Geräte bekommen eine ID im Bereich von 1...127.
</klug-scheiß-modus>

Scatter/Gather ist bei Netzwerkkarten eher vorgesehen, dass der Kernel den Header zusammenpopelt und dann im selben Paket die Nutzdaten aus dem Userspace hinterherschieben lässt, ohne die Daten in einen gemeinsamen Puffer kopieren zu müssen. Das ist eher nicht vorgesehen, dass der PMM so schlecht verwaltet wird, dass man die Pakete noch weiter splitten muss.
Wie Du ja selbst schreibst soll diese Technik es ermöglichen direkt die Daten der User-Space-Applikationen zu benutzen und die sind eben nicht ausgerichtet und können sich daher auch über mehrere Pages verteilen und diese Pages müssen nicht physisch zusammenhängend sein. Das hat nichts mit schlecht verwaltetem Speicher zu tun!


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: kevin am 08. September 2010, 15:50
Die PCI-Enumeration in mehreren Teilschritten zu erledigen ist einfach nicht vorgesehen (würde ja auch keinen Sinn ergeben).
Hm, ich habe davon ja keine Ahnung, aber wie funktioniert PCI-Hotplugging?
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 08. September 2010, 16:01
Zitat von: taljeth
Hm, ich habe davon ja keine Ahnung, aber wie funktioniert PCI-Hotplugging?
Dumme Antwort, aber die PCI Specs dürften da weiterhelfen ;)

Zitat von: erik
Natürlich könnte das OS die Ressourcenzuweisung noch mal komplett von neuem durchführen aber dann würden sich einige Adressen ändern (von bereits zugewiesenen Ressourcen) und das dürfte unangenehme Nebenwirkungen haben (vor allem weil es sich ja um wichtige Boot-Geräte handelt).
Warum sollte das unangenehme Nebenwirkungen ergeben? Oder um es anders zu Sagen, du wirst die Adresse/IO-Port mind. einmal ändern und zwar von jedem Gerät. Nämlich dann wenn du rausfinden willst wie groß der benutzte Bereich des Geräts ist. Da schreibt man üblicherweise 0xFFFFFFFF in das BAR um zu sehen, ob MMIO oder IO-Port und wie groß der Bereich halt ist. In dem Moment änderst du aber auch die Adresse.
Es ist also durchaus vorgesehen, das du das ganze selbst machst und taljeth Frage geht ja auch in die Richtung.

Zitat von: erik
Schon um jedem PCI-Gerät die richtige PCI-Geräte-Adresse, also Bus/Device/Function, zuzuweisen muss man den gesamten PCI komplett traversieren (durch alle Bridges hindurch).
Was hat das mit den Ressourcen zu tun? Zumal ich mir nicht mal sicher bin, das du (als OS) da noch was dran ändern kannst.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 08. September 2010, 16:34
Hallo,


aber wie funktioniert PCI-Hotplugging?
Das geht nur hinter einer Bridge und da reserviert das BIOS für die möglichen Geräte hinter der Bridge einfach etwas Speicher (und macht ne passende Weiterleitung in der Bridge), wenn die Geräte dann angeschlossen werden können die mit Ressourcen aus dieser Reserve konfiguriert werden. Falls die Geräte mehr benötigen ist das eben Pech.


aber die PCI Specs dürften da weiterhelfen
Leider nicht wirklich, Hot-Plugging ist bei PCI nicht standardisiert. Es gibt z.B. keinen einheitlichen Mechanismus mit dem man den Hot-Plug-Event mitgeteilt bekommt. Bei PCI-Express kann man sich damit behelfen in dem man einfach regelmäßig versucht die Serdes-Link-Ebene zu initialisieren bis was geht (eben pollen).

Warum sollte das unangenehme Nebenwirkungen ergeben? Oder um es anders zu Sagen, du wirst die Adresse/IO-Port mind. einmal ändern und zwar von jedem Gerät. Nämlich dann wenn du rausfinden willst wie groß der benutzte Bereich des Geräts ist. Da schreibt man üblicherweise 0xFFFFFFFF in das BAR um zu sehen, ob MMIO oder IO-Port und wie groß der Bereich halt ist. In dem Moment änderst du aber auch die Adresse.
Das ist was anderes, da ist hinterher ja wieder die selbe Adresse drin (falls Du alles richtig machst), aber wenn man die Ressourcenzuweisung wieder komplett von neuem laufen lässt ist hinterher eine andere Adresse drin (weil ja bei dem vorherigen Teildurchlauf, so wie Svenska ihn andeutet, eben nicht alle benötigten Ressourcen berücksichtigt wurden). Außerdem darf ein PCI-Gerät, während seine BARs analysiert werden, nicht benutzt werden und auch das decodieren von Zugriffen sollte disabled werden (siehe Wiki (http://www.lowlevel.eu/wiki/PCI#Beispiel-Code_zur_BAR-Analyse)).

Zitat von: erik
Schon um jedem PCI-Gerät die richtige PCI-Geräte-Adresse, also Bus/Device/Function, zuzuweisen muss man den gesamten PCI komplett traversieren (durch alle Bridges hindurch).
Was hat das mit den Ressourcen zu tun? Zumal ich mir nicht mal sicher bin, das du (als OS) da noch was dran ändern kannst.
Das hat mit den Ressourcen nicht direkt was zu tun aber um eben von jedem PCI-Gerät den Config-Space überhaupt ansprechen zu können muss auch jedem PCI-Gerät eine Geräte-Adresse (Bus/Device/Function) zugewiesen sein. Das OS könnte daran schon was ändern (wenn es die PCI-Enumeration + Ressourcen-Zuweisung noch mal neu durchführt) aber das sollte man besser lassen.


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 08. September 2010, 16:41
Zitat von: erik
Das ist was anderes, da ist hinterher ja wieder die selbe Adresse drin (falls Du alles richtig machst)
Wie kann da hinterher die selbe Adresse drin sein? Dann würde dir das ja nichts bringen. Damit willst du ja das Alignment (und damit die Größe) feststellen. Wimre dann speichert man vorher den alten Wert um ihn hinterher wieder einzutragen.
Ich lasse mich aber gerne eines besseren belehren, aber so hatte ich die Specs verstanden.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 08. September 2010, 17:05
Hallo,


Wie kann da hinterher die selbe Adresse drin sein?
Arrr ....  (ganz ruhig Erik, nicht aufregen)

Wimre dann speichert man vorher den alten Wert um ihn hinterher wieder einzutragen.
Eben deshalb ist hinterher (also nachdem man den BAR-Analyse-Vorgang komplett durchlaufen hat) wieder die selbe Adresse drin.


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 08. September 2010, 17:10
Zitat von: erik
Arrr ....  (ganz ruhig Erik, nicht aufregen)
;)

Der Punkt ist, ich habe trotzdem Recht  :-P (Die Ressourcen können geändert werden und das ist auch vorgesehen)

Ich möchte sogar behaupten das Linux und Windows Code haben für eine neue Ressourcenzuweisung und das es halt den Fall gibt das die Ressourcen gar nicht oder fehlerhaft zugewiesen wurden.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 08. September 2010, 17:54
Hallo,


Die Ressourcen können geändert werden und das ist auch vorgesehen
Hat das jemand bezweifelt?
Die Frage ist nur wie sinnvoll das ist.
Es macht auf jeden Fall keinen Sinn wenn das BIOS nur einen Teil der PCI-Geräte konfiguriert und den Rest dem OS überlasst eben weil sich damit die Adressen der vom BIOS konfigurierten Geräte ändern können und damit das BIOS nicht mehr funktionieren würde (also z.B. keinen INT 13h mehr anbieten kann).

Ich möchte sogar behaupten das Linux und Windows Code haben für eine neue Ressourcenzuweisung und das es halt den Fall gibt das die Ressourcen gar nicht oder fehlerhaft zugewiesen wurden.
Bei Windows würde ich das eher bezweifeln (außer für Hot-Plugging vielleicht) aber Linux hat solchen Code bestimmt. Linux kann mit Sicherheit die komplette PCI-Enumeration + Ressourcenzuweisung selber erledigen, es soll ja auch auf nicht PC-Systemen laufen wo es eventuell gar kein BIOS gibt. Ob Linux das auch auf einem normalen PC tut kann ich nicht beurteilen aber da es das BIOS ja nie in Anspruch nimmt dürfte es tatsächlich keine negativen Auswirkungen haben wenn alle PCI-Geräte neue Adressen zugewiesen bekommen (wobei ich nicht beurteilen kann ob da eventuell Suspend-to-RAM bzw. Suspend-to-Disk oder irgendwelche SMM-Dinge ein Problem darstellen).


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 08. September 2010, 23:07
Ursprünglich hat bei PnP-OS=Enabled das BIOS nur den zum Booten benötigten Geräten die Ressourcen zugeteilt. Und zwar auch nur auf der PCI-Host-Bridge, alles dahinter war nicht erreichbar. In den Systemen gab es auch nur einen PCI-Bus.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 09. September 2010, 14:23
Zitat von: erik
Es macht auf jeden Fall keinen Sinn wenn das BIOS nur einen Teil der PCI-Geräte konfiguriert und den Rest dem OS überlasst eben weil sich damit die Adressen der vom BIOS konfigurierten Geräte ändern können und damit das BIOS nicht mehr funktionieren würde (also z.B. keinen INT 13h mehr anbieten kann).
Dem wiederspreche ich mal. Solange du den Kompatibilitätsmodus des IDE-Kontrollers nicht ausstellst, ist der immer hinter den gleichen Ports erreichbar.
Außerdem hat Svenska doch gesagt, das nur das was zum Booten gebraucht wird initialisiert wird und dass das BIOS nach dem Booten eines OS noch funktioniert, davon gehe ich sowieso nicht aus. Wer weiß was das OS alles geändert hat, aber das ist ja auch sein gutes Recht ;)

Edit::

Habe das falsche "nicht" entfernt.
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: Svenska am 09. September 2010, 15:00
Äh, nur das, was zum Booten gebraucht wird, wird auch initialisiert; der Rest wird dem Betriebssystem überlassen. Das ist auch dafür nötig, eine BIOS-kompatible Umgebung herzustellen, sofern BIOS-Funktionen später benötigt werden.

Was willst du im Protected Mode auch mit einem int13h?

:-)
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: erik.vikinger am 09. September 2010, 18:08
Hallo,


dass das BIOS nach dem Booten eines OS noch funktioniert, davon gehe ich sowieso nicht aus
Okay und was ist mit der Emulation von Legacy-Devices (z.B. eines Floopy-Controllers obwohl ein USB-Floppy dran hängt) oder anderen Dingen für die SMM benötigt wird (z.B. Bildschirmhelligkeit bei Laptops)? Es gibt IMHO tausende Gründe warum das BIOS noch funktionieren sollte auch wenn das OS läuft.


Was willst du im Protected Mode auch mit einem int13h?
Massenspeicher ansprechen für die das OS keine eigenen Treiber hat (alle DOS-basierenden Windowsen können das und hier im Forum wurde das auch schon mal für unsere Hobby-OSe diskutiert).


Wieso streite ich mit Euch eigentlich darüber? In mein OS werde ich auf jeden Fall eine ordentliche PCI-Enumeration und Ressourcen-Vergabe implementieren müssen, ich hab ja auch kein BIOS, wenn Ihr das für Eure x86-OSe ebenfalls tun wollt dann bitte. Ich werde mich zu diesem Thema nicht mehr äußern!


Grüße
Erik
Titel: Re:Treiber bei einem Mikrokernel
Beitrag von: FlashBurn am 12. September 2010, 15:09
Um nochmal was zu dem Thema BIOS und PCI Ressourcen zu sagen, ich habe gerade mal auf meinem Sockel 940 (Opteron) Board im BIOS nachgeguckt und da steht als Erklärung für die genannte Option (Plug&Play OS available) das nur die Ressourcen initialisiert werden, die zum Booten nötig sind.
Damit kann man mit 100%er Sicherheit davon ausgehen, das auch Windows sowas beherrscht!