Autor Thema: Treiber "Management"  (Gelesen 18113 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #20 am: 22. September 2010, 16:30 »
@Svenska

So lange wie man nicht irgendetwas anderes bzw. andersartiges als das DMA "erfindet" was wir momentan haben, kann man sich gegen solche Sachen schwer bis gar nicht schützen, zumal aus 100% Sicherheit nie geben wird.
Programmierfehler wirst du auch in Treibern von vertrauenswürdigen Quellen haben.

Zitat von: svenska
Beispiel hierfür wäre "nvidia" gegen "vesa" - ersterer ist, auch wenn älter, sicherlich geeigneter - oder "Chipsatztreiber" gegen "PIO-IDE-Treiber".
Sehr gutes Bsp.! Meine Frage dazu wäre, wie man, wenn man Treiber anhand ihrer unterstützten Geräte irgendwo einsortiert, solche "allgemeinen" Treiber überhaupt behandelt?

Meine spontane Idee wäre, die Geräteart mit einem Hersteller den es nicht geben kann (sprich ein spezieller Code) dafür zu nutzen und sobal ein Treiber für ein Gerät von genau dem Hersteller vorhanden ist, nimmt man diesen anstatt einen für alle Hersteller.
Frage ist nur, gibt es einen solchen Hersteller-Code, der entweder "illegal" ist oder halt einfach nicht verwendet wird?

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #21 am: 22. September 2010, 17:17 »
Zitat von: svenska
Ich empfehle cat /proc/sys/net/ipv4/fuckups, einen Talk (knappe Stunde) vom letzten Chaos Communication Congress. Dort wird beschrieben, wie man durch eine Ansammlung kleiner, vereinzelter, an sich ungefährlicher Bugs in ein Netzwerk eindringen kann.
Warum? Unter anderem werden dort auch zwei Ethernet-Treiber missbraucht, um Payload als neues Paket an den Kernel weiterzureichen.
Ich habe mir das gerade mal angeschaut und von dem was ich verstanden habe (denke ich zumindestens ;) ), kann ich nur sagen, solch Code hat es verdient gecrackt zu werden ;)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 22. September 2010, 18:36 »
Hallo,


Zitat von: erik
Das diese Datenbank verwundbar ist wenn das System nicht läuft (und die Platte in einem anderen Rechner einbaut wird) ist mir klar
Sorry, aber an sowas denke ich nicht mal. Wenn es um Sicherheit geht und es möglich ist die Platte auszubauen, an einen anderen PC anzuschließen, die Daten darauf zu manipulieren und die Platte dann wieder zurück zu packen. Wozu dann noch Sicherheit unter deinem OS? Das ein OS zur Laufzeit nicht manipulierbar sein sollte ist klar, aber wenn obiges möglich ist, dann ist das auch egal. Soll heißen wenn es so wichtig ist dass das OS läuft bzw. das die Daten darauf so wichtig sind, dann sollte dieses Szenario überhaupt nicht möglich sein. Ergo wird es einfach ignoriert ;)
Für den physischen Zugriff auf ein System sind aber andere Voraussetzungen zu erfüllen als für den virtuellen Zugriff, ein Einbruch in einen Sicherheits-Server-Raum ist sicher deutlich schwieriger als einen öffentlich erreichbaren Server einfach per IP anzusprechen. Gegen den physischen Zugriff kann ich per SW faktisch nichts tun (also ignoriere ich das auch) aber gegen den virtuellen Zugriff sehe ich mich schon in der Pflicht da wenigstens die offensichtlichen Maßnahmen auch zu ergreifen (das ich kein Hochsicherheits-OS erstellen möchte ist wohl klar aber ganz und gar ignorieren möchte ich dieses Thema auch nicht). Wenn irgendwelche Wartungsarbeiten an Internet-Servern durchgeführt werden werden diese auch vom Netz genommen (und nach einem Treiber/Kernel-Update sicher auch neu gebootet). Wenn der angebotene Service sehr wichtig ist dann nimmt man eben mehrere redundante Server und klemmt immer nur einen ab.


So lange wie man nicht irgendetwas anderes bzw. andersartiges als das DMA "erfindet" was wir momentan haben, kann man sich gegen solche Sachen schwer bis gar nicht schützen, zumal aus 100% Sicherheit nie geben wird.
Das Problem am DMA ist das ein busmasterfähiges Gerät überall ran kann, sogar an die anderen Geräte (ein gehackter Ethernet-Treiber könnte auch die Daten in den Frame-Buffer umleiten). Schön wäre es wenn man zumindest bei externen Zugriffen auf den normalen RAM in Chipsatz ein paar Sperren hätte so das der Kernel wenigstens sich selber (und vielleicht noch Pages die die Applikationen als besonders sensibel markiert haben weil z.B. Passwörter drin liegen) schützen könnte.

Programmierfehler wirst du auch in Treibern von vertrauenswürdigen Quellen haben.
Aber keine gefährlichen Hintertüren, obwohl es da auch schon mehrere Gegenbeispiele gibt aber dagegen kann man sich eben nicht schützen (< 100%).

Meine spontane Idee wäre, die Geräteart mit einem Hersteller den es nicht geben kann (sprich ein spezieller Code) dafür zu nutzen und sobal ein Treiber für ein Gerät von genau dem Hersteller vorhanden ist, nimmt man diesen anstatt einen für alle Hersteller.
Frage ist nur, gibt es einen solchen Hersteller-Code, der entweder "illegal" ist oder halt einfach nicht verwendet wird?
Von dieser Idee würde ich lieber Abstand nehmen. Bei PCI gibt es dafür den Class-Code, Du musst bei Deinen Treibern nur sagen ob die anhand der Class-Codes oder anhand der Vendor/Product-ID zugeordnet werden sollen (die zweiten sind die spezielleren und sollten bevorzugt werden).


Grüße
Erik


Edit:
@Svenska: Danke für den Link
« Letzte Änderung: 22. September 2010, 18:39 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #23 am: 22. September 2010, 18:45 »
Das Beispiel lässt sich aber noch schön erweitern, so dass nicht mehr so klar ist, dass der eine Treiber der schlechtere generische und der andere der bessere spezielle ist: vesa/nv/nouveau/nvidia. Einmal generisch; einmal ein älterer freier Treiber; einmal ein neuerer, aber noch experimenteller; und zum Abschluss noch ein proprietärer vom Hersteller.

Da hat man wohl verloren, wenn man das automatisch entscheiden will.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #24 am: 22. September 2010, 19:11 »
Hallo,


und zum Abschluss noch ein proprietärer vom Hersteller.
Ich denke das dürfte bei all unseren OSen grundsätzlich auszuschließen sein. ;)

Da hat man wohl verloren, wenn man das automatisch entscheiden will.
Automatisch sollte man so komplexe Dinge IMHO gar nicht mehr entscheiden. Das Programm das die Datenbank (oder was auch immer) mit den Treibern zusammenstellt sollte prüfen das keine Kollisionen drin sind, also keine Vendor/Product-ID-Kombination doppelt vergeben ist und auch kein Class-Code doppelt vergeben ist. Die Entscheidung des Lade-Mechanismus, welchen Treiber er laden soll, muss immer eineindeutig sein. Im Zweifelsfall muss root vorher entscheiden.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #25 am: 22. September 2010, 19:15 »
Zitat von: erik
Schön wäre es wenn man zumindest bei externen Zugriffen auf den normalen RAM in Chipsatz ein paar Sperren hätte so das der Kernel wenigstens sich selber (und vielleicht noch Pages die die Applikationen als besonders sensibel markiert haben weil z.B. Passwörter drin liegen) schützen könnte.
Ich würde mir ne andere Variante als besser vorstellen. Nämlich ungefähr so wie bei ISA DMA, sprich wie DMA programmiert wird ist bekannt und bei allen Sachen gleich, sprich es ist im Standard drin (vielleicht ein extra Register im PCI CfgSpace). Dies ist natürlich für den gleichzeitigen Zugriff mehrerer Geräte ungünstig, aber das könnte man so lösen, das man halt nen Standard hat wie das geregelt wird (im MMIO Bereich).
Dann wäre es nämlich möglich die ganze DMA Geschichte nur über den Kernel oder einen Server laufen zu lassen und der Treiber an sich hätte gar kein Zugriff mehr darauf. Damit kannst du dein System dann zu annähernd 100% gegen Treiberfehler absichern (annähernd, weil einem von euch bestimmt ein Grund einfällt warum das nicht so ist ;) ).

Zitat von: erik
Von dieser Idee würde ich lieber Abstand nehmen. Bei PCI gibt es dafür den Class-Code, Du musst bei Deinen Treibern nur sagen ob die anhand der Class-Codes oder anhand der Vendor/Product-ID zugeordnet werden sollen (die zweiten sind die spezielleren und sollten bevorzugt werden).
Und genau das ist ja das Problem. Denn wie könnte man das machen?

Ich hatte mir eine Struktur die ungefähr so aussieht vorgestellt:
struct device_t {
 char busName[6]; //in dem Fall "PCI   "
 uint32t classCode;
 uint32t deviceID;
 uint32t vendorID;
}
Damit könnte ich dann eine VendorID und DeviceID von z.B. 0x10000 nehmen. Denn ansich sind die Sachen ja nur 16bit breit und so könnte ich die restlichen 16bit für genau solche Fälle nehmen.

Zitat von: taljeth
Das Beispiel lässt sich aber noch schön erweitern, so dass nicht mehr so klar ist, dass der eine Treiber der schlechtere generische und der andere der bessere spezielle ist: vesa/nv/nouveau/nvidia. Einmal generisch; einmal ein älterer freier Treiber; einmal ein neuerer, aber noch experimenteller; und zum Abschluss noch ein proprietärer vom Hersteller.
Naja, ich sags mal so, bei mir würde installiert/vorhanden heißen, wenn der Treiber in dem Treiberverzeichnis drin ist. Man sollte sich dann eventuell für später irgendetwas einfallen lassen um einen speziellen Treiber auszuwählen.
Ich habe mir als Ziel aber insbesondere gesetzt, das du das Medium wo mein OS drauf ist, nehmen kannst und in einen anderen PC steckst und da funktioniert es dann auch/trotzdem. Sollte auch funktionieren, da die wichtigen Sachen zum Booten ja eh generische Sachen sind (IDE/SATA/USB/SCSI)!?

Zitat von: erik
Die Entscheidung des Lade-Mechanismus, welchen Treiber er laden soll, muss immer eineindeutig sein. Im Zweifelsfall muss root vorher entscheiden.
Das wird bei meinen Zielen (siehe Oben) wohl sehr schwierig umzusetzen sein. Denn wie willst du den Benutzer fragen, wenn es sich z.B. um den Grafiktreiber handelt.
Was ich mir noch vorstellen könnte ist dass man erst mal generische Treiber nimmt (z.B. VBE) und dann wenn das System soweit ist, das Treiber nachgeladen werden können, sucht man nach spezielleren Treibern und nutzt die dann. Beim Bootvorgang sollte eine Geräteübergabe an einen anderen Treiber eigentlich noch möglich sein.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #26 am: 23. September 2010, 12:12 »
Hallo,


Ich würde mir ne andere Variante als besser vorstellen. Nämlich ungefähr so wie bei ISA DMA, sprich wie DMA programmiert wird ist bekannt und bei allen Sachen gleich, sprich es ist im Standard drin (vielleicht ein extra Register im PCI CfgSpace). Dies ist natürlich für den gleichzeitigen Zugriff mehrerer Geräte ungünstig, aber das könnte man so lösen, das man halt nen Standard hat wie das geregelt wird (im MMIO Bereich).
Dann wäre es nämlich möglich die ganze DMA Geschichte nur über den Kernel oder einen Server laufen zu lassen und der Treiber an sich hätte gar kein Zugriff mehr darauf. Damit kannst du dein System dann zu annähernd 100% gegen Treiberfehler absichern (annähernd, weil einem von euch bestimmt ein Grund einfällt warum das nicht so ist ;) ).
Das würde bedeuten das man Flexibilität und Funktionalität gegen Sicherheit eintauscht, ich denke dafür dürfte es nicht viele Unterstützer geben. Der Vorteil der PCI-Geräte ist doch gerade das jedes Gerät genau die Fähigkeiten hat die es benötigt. Wie sollte man mit so einer generischen Lösung z.B. TCP-Offloading für Ethernet-Controller realisieren? Selbst wenn Du jedem PCI-Gerät einen eigenen aber genormten DMA-Manager mitgibst dann muss dieser eben den kleinsten gemeinsamen Nenner darstellen, was quasi alle PCI-Geräte zu arg einschränken würde oder Du musst den perfekten Alleskönner als DMA-Manager spezifizieren der in den meisten PCI-Geräten nur unnötiges Silizium kostet und am Ende doch nicht die speziellen Wünsche des jeweiligen Gerätes zu 100% erfüllen kann. So verlockend diese Idee auch ist ich denke das ist extrem kontraproduktiv (und unrealistisch).

Zitat von: erik
Von dieser Idee würde ich lieber Abstand nehmen. Bei PCI gibt es dafür den Class-Code, Du musst bei Deinen Treibern nur sagen ob die anhand der Class-Codes oder anhand der Vendor/Product-ID zugeordnet werden sollen (die zweiten sind die spezielleren und sollten bevorzugt werden).
Und genau das ist ja das Problem. Denn wie könnte man das machen?
Was genau ist das Problem? Du findest ein PCI-Gerät und holst die Vendor/Product-IDs und den Class-Code und durchsuchst damit erst das Array mit den spezifischen Treibern, anhand Vendor/Product-ID, und danach (falls nichts spezifisches gefunden wurde) das Array mit den generischen Treibern, anhand des Class-Code.

Zitat von: erik
Die Entscheidung des Lade-Mechanismus, welchen Treiber er laden soll, muss immer eineindeutig sein. Im Zweifelsfall muss root vorher entscheiden.
Das wird bei meinen Zielen (siehe Oben) wohl sehr schwierig umzusetzen sein. ....
Trotzdem muss diese Entscheidung immer eineindeutig sein. Dann muss eben die Entscheidung von root mit in die Datenbank mit aufgenommen werden oder man braucht andere klare Regeln. Man könnte z.B. immer sagen das auf unbekannten Systemen (für die root noch keine explizite Entscheidung getroffen hat) immer erst mal generische Treiber bevorzugt werden sollen. Und ansonsten darf es in der Datenbank eben keine Kollisionen geben, das Beispiel von taljeth ist in der Hinsicht IMHO fehlerhaft, es sollte nicht möglich sein mehrere spezifische Treiber für das selbe Gerät (also identische Vendor/Product-IDs) zu installieren. Das gilt IMHO auch für die generischen Treiber, auch hier sollte es nicht möglich das mehrere Treiber für ein und den selben Class-Code zuständig sind.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #27 am: 23. September 2010, 13:21 »
@erik

Andere Idee  :-D

Was wäre wenn man DMA über die MMU (sowas wie ne IOMMU gibt es ja bei AMD schon, ob dass ungefähr das ist was ich meine weis ich aber nicht) laufen lassen würde. Sprich du initialisierst den DMA Kontroller mit dem PageDir (also den Wert von CR3 des Treibers, der sollte sich eigentlich nicht ändern) und dann übergibst du immer die virtuelle anstatt der physischen Adresse? Würde das nicht alle Probleme lösen und trotzdem alles andere wie gewohnt zulassen?

Zitat von: erik
Was genau ist das Problem? Du findest ein PCI-Gerät und holst die Vendor/Product-IDs und den Class-Code und durchsuchst damit erst das Array mit den spezifischen Treibern, anhand Vendor/Product-ID, und danach (falls nichts spezifisches gefunden wurde) das Array mit den generischen Treibern, anhand des Class-Code.
Das Problem ist, wie erstellst du das Array mit den generischen Treibern, wenn man diese nur anhand der IDs bestimmen kann.
Ich wollte eine Struktur für beide Arten von Treibern und wenn es da keinen Wert für die VendorID gibt, der laut PCI Specs nicht zugelassen ist, dann hast du nur spezielle Treiber, erweitere ich aber die VendorID auf 32bit, kann ich Werte haben die nicht zugelassen sind und kann so meine generischen Treiber erkennen.

Zitat von: erik
Das gilt IMHO auch für die generischen Treiber, auch hier sollte es nicht möglich das mehrere Treiber für ein und den selben Class-Code zuständig sind.
Ich weis nicht ob wir jetzt von der selben Sache reden, aber was ist mit einem IDE Treiber für Intel-Chipsätze, einem für SIS-Chipsätze usw. die haben alle den selben Class-Code und werden erst über den Vendor bestimmt.
Selbe für Grafikkarten, die haben alle den selben Class-Code, nur andere VendorIDs.
Selbst unter Windows kann man mehrere Treiber für ein und das selbe Gerät haben, es wird halt immer nur einer genutzt (der dann in der Registry eingetragen ist).

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #28 am: 23. September 2010, 14:49 »
Hallo,


Was wäre wenn man DMA über die MMU (sowas wie ne IOMMU gibt es ja bei AMD schon, ob dass ungefähr das ist was ich meine weis ich aber nicht) laufen lassen würde. ....
Diese IOMMU ist wimre für die Virtuallisierung gedacht aber es müsste auch möglich sein die IOMMU für die Sicherheit einzusetzen. Das Problem welches ich sehe ist das man sehr viele dieser IOMMUs bräuchte, für jeden gerade laufenden Vorgang eine. Und das Gerät müsste auch für jeden Vorgang genau wissen welche dieser IOMMUs es benutzen soll, ein SATA/AHCI-Host-Controller kann ja durchaus mehrere Anfragen verschiedener Clients parallel bearbeiten. Ich bin mir nicht sicher ob sich dieses Problem wirklich zuverlässig in Hardware lösen lässt, ich hab da für meine Plattform schon mal drüber nachgedacht und bin auf keine gescheite Lösung gekommen. Alles was mir dazu eingefallen ist sind mehrere Range-Register im Chip-Satz die bestimmen auf welche Speicherbereiche die HW zugreifen darf (positiv Decoding) oder welche Speicherbereiche verboten sind (negativ Decoding). Für ersteres bräuchte man eventuell sehr viele dieser Register weil die Daten ja im physischen RAM wild zerstreut sein können und mit letzterem kann der Kernel eigentlich nur sich selbst etwas beschützen falls er nicht zu zerstreut im physischen RAM liegt (was auf meiner Plattform sicher gegeben ist). Das Problem das so ein Filtermechanismus zusätzliche Latenz (die mit mehr Registern auch größer wird) beim Speicherzugriff der Geräte erzeugt bleibt in jedem Fall erhalten. Man würde also für ein kleines bisschen Sicherheit ein kleines bisschen Performance opfern. Das beste was ein OS tun kann ist, wenn es für die Treiber von virtuell an physisch umrechnet, möglichst genau hinzuschauen ob der Treiber auf die virtuellen Adressen überhaupt zugreifen darf.


Das Problem ist, wie erstellst du das Array mit den generischen Treibern, wenn man diese nur anhand der IDs bestimmen kann.
Du könntest ein enum dazu packen das entscheidet was für ein Treiber das ist. Für die Product/Vendor-IDs sind IMHO 0x0000 und 0xFFFF verboten (eventuell nur wenn Vendor-ID == Product-ID ist) und es gibt auch ungültige Class-Codes, wenn Du das genau wissen möchtest musst Du in die PCI-Spec schauen (wenn Du möchtest kann ich das heute Abend mal machen), aber sauber ist dieser Weg meiner Meinung nach nicht.

Ich weis nicht ob wir jetzt von der selben Sache reden, aber was ist mit einem IDE Treiber für Intel-Chipsätze, einem für SIS-Chipsätze usw. die haben alle den selben Class-Code und werden erst über den Vendor bestimmt.
Selbe für Grafikkarten, die haben alle den selben Class-Code, nur andere VendorIDs.
Hier wäre das enum wieder gut, Du köntest nicht nur einen Typ für generisch (Class-Code) und einen Typ für spezifisch (Vendor/Porduct-ID) haben sondern auch zusätzliche Mischformen wie eben Class-Code + Vendor-ID (ohne Product-ID) so könntest Du alle IDE-Controller/Grafikkarten eines bestimmten Herstellers in eine Gruppe sortieren.

Selbst unter Windows kann man mehrere Treiber für ein und das selbe Gerät haben, es wird halt immer nur einer genutzt (der dann in der Registry eingetragen ist).
Bei Windows ist die Registry die Datenbank und was da nicht drin steht wird auch nicht zu booten benutzt, erst wenn der User Windows anweist einen neuen Treiber zu suchen (bzw. Windows den User frag ob es nach einem neuen suchen soll) kommt auch ein neuer Treiber in die Registry und wird auch erst nach dem nächsten Boot aktiv.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #29 am: 23. September 2010, 15:03 »
Zitat von: erik
Das beste was ein OS tun kann ist, wenn es für die Treiber von virtuell an physisch umrechnet, möglichst genau hinzuschauen ob der Treiber auf die virtuellen Adressen überhaupt zugreifen darf.
Naja, das ist das was ich machen will, löst das eigentlich Problem aber nicht wirklich, denn der Treiber kann noch immer hinschreiben wo er lustig ist.

Zitat von: erik
Für die Product/Vendor-IDs sind IMHO 0x0000 und 0xFFFF verboten (eventuell nur wenn Vendor-ID == Product-ID ist) und es gibt auch ungültige Class-Codes, wenn Du das genau wissen möchtest musst Du in die PCI-Spec schauen (wenn Du möchtest kann ich das heute Abend mal machen), aber sauber ist dieser Weg meiner Meinung nach nicht.
Naja, das ist doch genau sowas was ich gesucht habe, aber da ich eigentlich schon die IDs auf 32bit erweitern wollte (die 6bytes sind dann auch nicht so schlimm) ist das eigentlich auch egal.
Was gefällt dir daran nicht bzw. denke ich mal du siehst da irgendwo ein Problem?

Zitat von: erik
Bei Windows ist die Registry die Datenbank und was da nicht drin steht wird auch nicht zu booten benutzt, erst wenn der User Windows anweist einen neuen Treiber zu suchen (bzw. Windows den User frag ob es nach einem neuen suchen soll) kommt auch ein neuer Treiber in die Registry und wird auch erst nach dem nächsten Boot aktiv.
Das ist genau das was ich auf keinen Fall haben will. Mir hat die Idee immer gefallen, das du dein USB-Stick, mit dem OS darauf, nimmst und an nen anderen PC steckst und schon läuft das OS ohne das es Probleme gibt (das z.B. der Treiber nicht in der Registry steht oder nicht im Bootscript steht oder nicht in den Kernel kompiliert ist).

Zu dem Thema passt doch eigentlich ne LiveCD auf Linux-Basis. Wie wird das dort gemacht? Sind da alle Treiber in irgendeinem Skript eingetragen (denn im Kernel sind die ja nicht mehr, sondern als externe Module)?

Was so auch noch nicht gemacht wurde (außer vielleicht bei Windows, da ist es in den INF-Dateien) das die Treiber nicht nachgucken ob ein Gerät für sie vorhanden ist (das wird bei Linux, möchte ich meinen, noch so gemacht) sondern das der Treiber auch nur geladen wird, wenn ein Gerät für ihn vorhanden ist.
Damit kann man einiges an Zeit einsparen (denke ich doch). Zumindest sollte sich der Bootvorgang so wesentlich beschleunigen lassen.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #30 am: 24. September 2010, 02:20 »
Hallo,

im Fall "ich habe einen generischen VESA-Treiber und einen speziellen i915-Treiber...welchen nehm ich?" sollte man immer den speziellen Treiber bevorzugen. Einfacher Grund: Es gibt silicon bugs in Hardware oder schlecht geschriebene Treiber. Dein generischer Treiber nutzt vielleicht (BIOS-/ROM-)Funktionen, die die Hardware "an sich selbst vorbei" programmieren und das führt eventuell später dazu, dass ein Wechsel nicht mehr möglich ist (Beispiel: vesafb/viafb gegen openchrome gegen via_chrome9. Wechsel von einem zum anderen führt zum Totalabsturz.)

Erst, wenn kein spezieller Treiber mehr vorhanden ist, wird der generische Treiber geladen. Als Vendor-/Device-ID sollte 0x0000 freigegeben sein. Die Werte würde ich übrigens im Treiber jeweils als 16bit-Werte speichern - weil es so ohnehin im Standard steht. Warum mehr? Vorteile hast du keine, Nachteile auch nicht. (Zumal du dir, wenn du eigene PCI-IDs erzeugst, möglicherweise mehr Ärger beschaffst als nötig. Und inband signalling ist sowieso ganz schlecht!)

Im Falle, dass mehrere spezielle Treiber für ein Gerät vorhanden sind, sollte der Nutzer gefragt werden, oder man nimmt einfach beide. Wenn der erste erfolgreich arbeitet, sind die Ressourcen für die Hardware belegt und der zweite Treiber funktioniert dann nicht. Warum siehe weiter unten.

Gegen den Fall, dass ein Treiber mittels DMA wahllos im Adressraum rumschreibt, kannst du als OS-Programmierer nichts tun. Sinnvoll wäre hier höchstens, die Treiber so zu gestalten, dass sie dies nicht tun - und das heißt, im Treiber prüfen.

Was die Linux-Live-CDs angeht, so hast du im Kernel einen Teil der Geräte fest eingetragen (Linux ist modularisiert, aber monolithisch), ansonsten wird eine initrd (initiale Ramdisk, neuerdings meist initramfs = ein zu entpackendes cpio-Archiv) vom Bootloader mitgeladen. Diese dient als Root-Dateisystem und enthält eine Menge an für diesen Kernel kompilierten Treibern; es werden davon die geladen, welche im System vorhandene Hardware unterstützen. Es gibt eine Datenbank, die wird mit "depmod" erzeugt und enthält nur die Modulabhängigkeiten zueinander, d.h. "snd-hda-intel" braucht "sndcore" braucht "snd", oder "ne2" braucht "8390", oder "pcnet_cs" braucht "8390", "pcmcia_cs" und "pcmcia" etc.pp. Das wird bei verschachtelten Treibern nötig.

Wobei es da möglicherweise sinnvoll ist, die Treiber grundsätzlich über eine Abstraktion (z.B. der Bussysteme) zu führen - also einer API - oder (einfacher) diese Abhängigkeiten mit in die Module zu packen. "modprobe" verarbeitet jedenfalls diese dependencies, "insmod" nicht. In letzterem Fall musst du die bedingten Treiber vorher selbst laden.

Unter Linux schaut jeder Treiber ohnehin auf die Hardware - es ist nämlich wichtig, ob "ath" auch die entsprechende Chipversion unterstützt. Es gibt (gab?) auch zwei Module für RTL8139: 8139cp (RTL8139 C+) und 8139too (RTL8139 außer C+ und ähnliche). Das wiederum wird nötig, wenn du mehrere Geräte gleicher PCI-IDs hast. Der Windowstreiber besteht dann aus zwei Treibern, die erst den Chipsatz untersuchen.

Treiber werden aber grundsätzlich nur geladen, wenn die entsprechende Hardware auch vorhanden ist - das ist bei Linux so. Ausnahmen gibt es nur, wenn du Treiber für ISA-Geräte hast; diese werden aber nicht mehr grundsätzlich geladen, sondern müssen (mit Parametern) in z.B. /etc/modules aufgeführt werden.

Um den Bootvorgang vollständig unabhängig zu halten, solltest du alle bootkritischen Treiber in deinem Kernel vorliegen haben. Ob das über eine (nachzuladende = anpassbare) initiale Ramdisk läuft oder über ein in die Kernelbinary eingebautes Dateisystem (wie es Award-BIOSse für das BIOS-ROM machen), kannst du entscheiden. Oder du lässt die Module von deinem Multiboot-Bootloader mitladen, allerdings müsstest du dann die Konfiguration jeweils an das System anpassen. Für die LiveCD-Konfiguration lässt du dann halt nur generische Treiber laden bzw. hast eine angepasste Liste vorliegen.

edit:
Zu dem Video: Bedenke, dass das in dem Code nur subtile Bugs waren, die eventuell auch nur auf bestimmten Revisionen funktionieren. Und, dass der relevante Abschnitt in einer/zwei von hunderten Codezeilen steckt - versteckt in Code, der eine Hardware mit/ohne Datenblatt korrekt ansteuern muss. Da passieren Fehler. Wenn du behauptest, du kriegst das besser hin, dann enttäusche ich dich unbesehen.

Gruß,
Sebastian
« Letzte Änderung: 24. September 2010, 02:48 von Svenska »

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #31 am: 24. September 2010, 09:08 »
Zitat von: svenska
Die Werte würde ich übrigens im Treiber jeweils als 16bit-Werte speichern - weil es so ohnehin im Standard steht. Warum mehr? Vorteile hast du keine, Nachteile auch nicht. (Zumal du dir, wenn du eigene PCI-IDs erzeugst, möglicherweise mehr Ärger beschaffst als nötig. Und inband signalling ist sowieso ganz schlecht!)
Weil ich meistens alles zumindest auf 4byte aligne. Wenn es aber im PCI Standard Werte gibt die ohne hin nicht zugelassen sind dann kann ich die natürlich nutzen.
Ich würde so ja keine neuen PCI-IDs (wenn man es genau nimmt nur eine ;) ) erzeugen sondern einfach nur einen Wert wie z.B. 0xDEADBEEF als ne Art Konstante damit ich weis das ist ein generischer Treiber.

Zitat von: svenska
Wobei es da möglicherweise sinnvoll ist, die Treiber grundsätzlich über eine Abstraktion (z.B. der Bussysteme) zu führen - also einer API - oder (einfacher) diese Abhängigkeiten mit in die Module zu packen. "modprobe" verarbeitet jedenfalls diese dependencies, "insmod" nicht. In letzterem Fall musst du die bedingten Treiber vorher selbst laden.
Genau für sowas macht sich mein Konzept ganz gut. Ich bin mir gerade zwar nicht sicher das wir vom selben Thema sprechen aber egal.
Ich wollte diese Abstraktion von Bussystemen auf jeden Fall machen (zumindest ISA/PCI/USB) und die Abhängigkeiten (die ich momentan sehe, kann sein das dann doch noch andere hinzu kommen) lösen sich von ganz alleine. Denn wenn kein PCI-Busmanager geladen und gestartet ist, werden die anderen Treiber auch nicht benötigt, da noch gar keine Geräte vorhanden sind.

Zitat von: svenska
Treiber werden aber grundsätzlich nur geladen, wenn die entsprechende Hardware auch vorhanden ist - das ist bei Linux so.
Ok, das wusste ich nicht. Aber wie funktioniert dann das installieren eines neuen Treibers? Muss der Kernel dann neu kompiliert werden oder wird der Treiber in irgendein Bootskript eingetragen und wird mitgeladen auch wenn er vielleicht gar nicht benötigt wird?

Zitat von: svenska
Oder du lässt die Module von deinem Multiboot-Bootloader mitladen, allerdings müsstest du dann die Konfiguration jeweils an das System anpassen.
Naja, ich wollte dann meinen Loader alle wichtigen Treiber (so fern vorhanden) laden lassen (PCI, USB, IDE, SATA, USB-MSD). Ob das dann auch so klappt oder ich das nochmal über den Haufen werfen muss, werd ich dann sehen.

Zitat von: svenska
Zu dem Video: Bedenke, dass das in dem Code nur subtile Bugs waren, die eventuell auch nur auf bestimmten Revisionen funktionieren. Und, dass der relevante Abschnitt in einer/zwei von hunderten Codezeilen steckt - versteckt in Code, der eine Hardware mit/ohne Datenblatt korrekt ansteuern muss. Da passieren Fehler. Wenn du behauptest, du kriegst das besser hin, dann enttäusche ich dich unbesehen.
Ich habe schon wirklich schöne Bugs produziert, vorallem finden sich meine Bugs immer so schwer (weil ich sie immer an der falschen Stelle vermute).
Aber was da manchmal gemacht wurde ist ein "try&fail"-Verfahren. Vorallem fand ich es gut, wenn man einen Patch dann wieder rückgängig macht und der Fehler ist wieder da ;)
Zumal das ja teilweise Code von den Leuten war die die Dokumentation haben müssten (z.B. Intel bei ihrer eigenen Hardware).

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #32 am: 24. September 2010, 13:56 »
Hallo,

Zitat von: svenska
Die Werte würde ich übrigens im Treiber jeweils als 16bit-Werte speichern - weil es so ohnehin im Standard steht. Warum mehr?
Weil ich meistens alles zumindest auf 4byte aligne.
Okay, das ist natürlich ein Grund. ;-)

Ich wollte diese Abstraktion von Bussystemen auf jeden Fall machen (zumindest ISA/PCI/USB) und die Abhängigkeiten (die ich momentan sehe, kann sein das dann doch noch andere hinzu kommen) lösen sich von ganz alleine. Denn wenn kein PCI-Busmanager geladen und gestartet ist, werden die anderen Treiber auch nicht benötigt, da noch gar keine Geräte vorhanden sind.
Naja, ich bezog mich bei Abhängigkeiten zwischen Treiberdateien auch darauf, dass du bei ähnlicher Hardware eine gewisse Menge an "common code" hast und den wiederum als eigenen Treiber auslagerst (8390.o gemeinsam für "ne", "ne2", "ne2k-pci", "pcnet_cs", weil alles ne2000 ist). Dann hast du so eine einfache Abhängigkeit nicht mehr.

Spielt aber erstmal nur untergeordnet eine Rolle.

Zitat von: svenska
Treiber werden aber grundsätzlich nur geladen, wenn die entsprechende Hardware auch vorhanden ist - das ist bei Linux so.
Ok, das wusste ich nicht. Aber wie funktioniert dann das installieren eines neuen Treibers? Muss der Kernel dann neu kompiliert werden oder wird der Treiber in irgendein Bootskript eingetragen und wird mitgeladen auch wenn er vielleicht gar nicht benötigt wird?
Warum solltest du neue Treiber installieren? :-)

Du hast in /lib/modules/`uname -r`/* deine Treiberdateien als Kernelmodule (.ko) liegen und der Kernel lädt die halt, wenn er die entsprechende Hardware findet. Diese Module werden beim Neukompilieren des Kernels ebenfalls neu erzeugt, sie sind Kernelspezifisch. (Darum hat der nvidia-Treiber auch einen kleinen Opensource-Anteil: Den Glue-Code zwischen binary blob und Kernel.)

In /etc/modules kannst du Module einfügen, die er immer laden soll und in /etc/modprobe.d/blacklist trägst du Module ein, die du unter keinen Umständen automatisch geladen haben möchtest.

Je nach Distribution wird zusätzlich zu einem Kernel-Update auch die initrd/initramfs neu erzeugt, sodaß diese dann die (evtl nur bootkritischen) Module in zum Kernel passender Version enthält.

Da die meisten Treiber zum Kernel gehören, hast du natürlich weniger Stress mit Treiberupdates. Bei Treibern, die außerhalb des Kernels gewartet werden (nvidia, manche WLAN-Treiber) ist das etwas schwieriger - das läuft dann meistens über die Distributionen, die vorkompilierte passende Module bereitstellen (Debian: "nvidia-glx") oder eine automatische Bauvorrichtung mitbringen (Debian: "dkms"). Man kann Kernelmodule auch außerhalb des Kernel-Sourcetrees bauen, wenn man die passenden Header hat.

Zitat von: svenska
Oder du lässt die Module von deinem Multiboot-Bootloader mitladen, allerdings müsstest du dann die Konfiguration jeweils an das System anpassen.
Naja, ich wollte dann meinen Loader alle wichtigen Treiber (so fern vorhanden) laden lassen (PCI, USB, IDE, SATA, USB-MSD). Ob das dann auch so klappt oder ich das nochmal über den Haufen werfen muss, werd ich dann sehen.
Das sollte funktionieren.

Ich habe schon wirklich schöne Bugs produziert, vorallem finden sich meine Bugs immer so schwer (weil ich sie immer an der falschen Stelle vermute).
Aber was da manchmal gemacht wurde ist ein "try&fail"-Verfahren. Vorallem fand ich es gut, wenn man einen Patch dann wieder rückgängig macht und der Fehler ist wieder da ;)
Zumal das ja teilweise Code von den Leuten war die die Dokumentation haben müssten (z.B. Intel bei ihrer eigenen Hardware).
Das ändert aber nichts daran, dass du dir im Datenblatt anschaust "Mensch, der sollte mit diesem/jenem Feature klarkommen, machen wir das" und nicht mitkriegst, dass vier Jahre vorher jemand anders schon festgestellt hat, dass eben dieses Feature nicht so tut wie im Datenblatt angegeben. Oder dass plötzlich ganz anderes Verhalten auftritt - an völlig fremden Stellen.

Treiberentwicklung ist zu einem Großteil "try&error". Das sehe ich bei nouveau/openchrome, aber auch bei meiner Fritzbox, wo ich dem eth-Entwickler leider ständig sagen muss "geht immernoch nicht". (Das sind 2 Schnittstellen auf einem Chip. Viele Geräte haben einen konfigurierbaren Switch dahinter angeschlossen. Die meisten restlichen nutzen einfach den ersten Anschluss, Fritzboxen nutzen den zweiten. Die automatische Erkennung der Verkabelung ist broken und so richtig weiß keiner, wie man das zuverlässig erkennen kann.) Wichtig ist, dass es erstmal funktioniert und dann fasst es keiner mehr an. Subtile Fehler tauchen dann später auf. Linux 2.6.36 behebt auf Alpha einen 14-Jahre alten Bug, den man erst jetzt gefunden hat. Und da haben viele Leute gesucht.

Und wenn du den universellen VESA-Treiber geschrieben hast, mit Unterstützung von S3 Trio32 (VBE1) bis nVidia mit Refreshsettings (VBE3), dann fällt dir eine Karte in die Hand, die behauptet, sie könne es besser als sie es kann. Und dein Treiber schlägt der Länge nach hin. :-P

Gruß,
Sebastian

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #33 am: 24. September 2010, 14:23 »
Zitat von: svenska
Naja, ich bezog mich bei Abhängigkeiten zwischen Treiberdateien auch darauf, dass du bei ähnlicher Hardware eine gewisse Menge an "common code" hast und den wiederum als eigenen Treiber auslagerst (8390.o gemeinsam für "ne", "ne2", "ne2k-pci", "pcnet_cs", weil alles ne2000 ist). Dann hast du so eine einfache Abhängigkeit nicht mehr.
Gut, wie gesagt, ich habe noch nicht wirklich Erfahrung in der Treiber-Programmierung, aber ich würde wahrscheinlich alles dann halt doppelt und dreifach als binary-Code vorliegen haben. Das man den Source mitverwenden kann ist ja was ganz anderes.

Zitat von: svenska
Warum solltest du neue Treiber installieren?
Naja, nicht OpenSource Treiber bzw. finde ich es eher unglücklich das Treiber so sehr zum Kernel gehören, das dieser diese schon zur compile-Zeit kennen muss. Sowas will ich in meinem OS absolut nicht.
Wenn Treiber im UserMode laufen, sollte das auch besser funktionieren, da sie da nicht ganz so viel Schaden anrichten können.

Ich will jedenfalls nicht für jeden Treiber meinen Device-Server neu kompilieren müssen und ich will mir die Option offen halten, das auch andere Treiber programmieren können und das man diese nachträglich "installieren" kann ohne das etwas kompiliert werden muss.

Zitat von: svenska
Das ändert aber nichts daran, dass du dir im Datenblatt anschaust "Mensch, der sollte mit diesem/jenem Feature klarkommen, machen wir das" und nicht mitkriegst, dass vier Jahre vorher jemand anders schon festgestellt hat, dass eben dieses Feature nicht so tut wie im Datenblatt angegeben. Oder dass plötzlich ganz anderes Verhalten auftritt - an völlig fremden Stellen.
Eigentlich darf ich das jetzt nicht sagen (da ich es selbst nicht wirklich mache, gerade bei solchen Sachen nicht), aber sollte man sowas nicht dokumentieren, damit genau sowas nicht passieren kann?

Vorallem merkt man an solchen Bsp wieder mal wie sehr doch die Uni-Welt und die reale Welt auseinander sind ;)

Wäre die Welt da draußen so wie sie dir in der Uni beschrieben wird, dann würden die Leute (wenigstens innerhalb eines Unternehmens) miteinander kommunizieren und der Bug wird entweder behoben oder wird in die Dokumentation aufgenommen.

Zitat von: svenska
Und wenn du den universellen VESA-Treiber geschrieben hast, mit Unterstützung von S3 Trio32 (VBE1) bis nVidia mit Refreshsettings (VBE3), dann fällt dir eine Karte in die Hand, die behauptet, sie könne es besser als sie es kann. Und dein Treiber schlägt der Länge nach hin.
Davon gehe ich jetzt mal bei allen meinen Treibern aus. Ich lerne ja noch, da wird wohl kein Treiber perfekt werden ;)

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #34 am: 24. September 2010, 15:13 »
Hallo,

Zitat von: svenska
Warum solltest du neue Treiber installieren?
Naja, nicht OpenSource Treiber bzw. finde ich es eher unglücklich das Treiber so sehr zum Kernel gehören, das dieser diese schon zur compile-Zeit kennen muss. Sowas will ich in meinem OS absolut nicht.
Das bedeutet, dass du eine Binärschnittstelle zur Verfügung stellen musst, mit der deine Treiber mit dem System reden. Linux hat das aus gutem Grund nicht - es soll Herstellern so schwer wie möglich gemacht werden, Closed Source-Treiber zu benutzen.

Selbst Broadcom hat jetzt eingelenkt und es gibt inzwischen freie Treiber von denen. Damit kannst du natürlich nicht rechnen. Die BSDs haben übrigens auch keine feste Treiber-ABI, aber da durch die Lizenz alles freigegeben ist, können die Hersteller alles selbst basteln.

Wenn Treiber im UserMode laufen, sollte das auch besser funktionieren, da sie da nicht ganz so viel Schaden anrichten können.
Falscher Ansatz - sie können unendlich viel Schaden anrichten. Die richtige Frage ist, ob du den Treibern soweit vertraust, dass sie es nicht tun.

Ich will jedenfalls nicht für jeden Treiber meinen Device-Server neu kompilieren müssen und ich will mir die Option offen halten, das auch andere Treiber programmieren können und das man diese nachträglich "installieren" kann ohne das etwas kompiliert werden muss.
Geht unter Linux ja auch, inzwischen auch automatisiert in den Distributionen. Es ist nur schwieriger.

Dazu kommt halt auch, dass manche Schnittstellen als GPLONLY deklariert sind (weil Hersteller sich bekanntermaßen nicht daran halten), und weil es ein großer Monolith ist, in dem Treiber alle möglichen Kernelfunktionen aufrufen können. Ändern diese sich, so muss der Treiber angepasst werden.

Legst du die Treiberschnittstelle fest, dann bist du gezwungen, sie kompatibel zu halten und (wenn sich deine Schnittstelle als unzureichend erweist) musst dann parallel mehrere dieser Schnittstellen anbieten (können). Das ist dann eine Frage der Skalierbarkeit: Bei 10 Treibern ist es egal, bei 10k Treibern essentiell wichtig. Vergleiche die frühen Linux-WLAN-Treiber (mit eigenem Stack, nur unverschlüsselt/WEP) mit den etwas späteren ("SoftMAC" WLAN-Stack, allerdings nicht in den Kernel aufgenommen) und den aktuellen ("mac80211" WLAN-Stack, im Kernel).

mac80211-Treiber können (mit Ausnahmen) alle WEP, WPA, WPA2, Monitor Mode und Host Mode. Der Stack ist so primitiv (und mächtig), dass eventuelle WEP-Hardware nicht genutzt werden kann - allerdings kann dadurch jede Karte WPA2. Die Arbeit wird dem Treiber abgenommen und in der CPU erledigt.

Zitat von: svenska
Das ändert aber nichts daran, dass du dir im Datenblatt anschaust "Mensch, der sollte mit diesem/jenem Feature klarkommen, machen wir das" und nicht mitkriegst, dass vier Jahre vorher jemand anders schon festgestellt hat, dass eben dieses Feature nicht so tut wie im Datenblatt angegeben. Oder dass plötzlich ganz anderes Verhalten auftritt - an völlig fremden Stellen.
Eigentlich darf ich das jetzt nicht sagen (da ich es selbst nicht wirklich mache, gerade bei solchen Sachen nicht), aber sollte man sowas nicht dokumentieren, damit genau sowas nicht passieren kann?
Wenn du es als Hersteller nicht weißt, nicht vorhersehen kannst oder es aufgrund von Fehlern passiert, dann steht es nicht in der Dokumentation. Darum gibt es Errata: "Ups, wir haben einen Fehler gefunden. Guck mal."

Nicht gefundene Fehler stehen da nicht drin. Und Fehler, die grobe Sicherheitslücken sein können oder genug Interna bereitstellen, werden aus politischen Gründen nicht immer dokumentiert. (Eine Fehlerbeschreibung, die gut genug für Workarounds ist, ist meist auch gut genug für Exploits.)

Zitat von: svenska
Und wenn du den universellen VESA-Treiber geschrieben hast, mit Unterstützung von S3 Trio32 (VBE1) bis nVidia mit Refreshsettings (VBE3), dann fällt dir eine Karte in die Hand, die behauptet, sie könne es besser als sie es kann. Und dein Treiber schlägt der Länge nach hin.
Davon gehe ich jetzt mal bei allen meinen Treibern aus. Ich lerne ja noch, da wird wohl kein Treiber perfekt werden ;)
Ich meinte: Dein Treiber sei jetzt perfekt und optimal. Dann stolpert er über nicht-perfekte Hardware.

Das eine (perfekter Treiber) widerspricht dem anderen (perfekte Hardware). Also entsteht eine Mischung aus try&error, whitelists, blacklists und Workarounds.

Damit musst du leben und wenn du dir über sowas beim Design einen Kopf machst, kann es nur leichter werden. ;-)

Gruß

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #35 am: 24. September 2010, 15:49 »
Zitat von: svenska
Das bedeutet, dass du eine Binärschnittstelle zur Verfügung stellen musst, mit der deine Treiber mit dem System reden. Linux hat das aus gutem Grund nicht - es soll Herstellern so schwer wie möglich gemacht werden, Closed Source-Treiber zu benutzen.
Das ist halt ne Philosophie-Entscheidung.

Zitat von: svenska
Falscher Ansatz - sie können unendlich viel Schaden anrichten. Die richtige Frage ist, ob du den Treibern soweit vertraust, dass sie es nicht tun.
Ich dachte mit DMA wären wir uns einig das man da leider nichts machen :(

Zitat von: svenska
Geht unter Linux ja auch, inzwischen auch automatisiert in den Distributionen. Es ist nur schwieriger.
Falscher Thread, aber egal. Ich behaupte mal genau solche Schwierigkeiten (und das ein Treiberupdate auch meisten nen Kernelupdate bedeutet) verhindern das Linux jemals bei einem Otto-Normal-Verbraucher großartig genutzt wird.

Zitat von: svenska
Legst du die Treiberschnittstelle fest, dann bist du gezwungen, sie kompatibel zu halten und (wenn sich deine Schnittstelle als unzureichend erweist) musst dann parallel mehrere dieser Schnittstellen anbieten (können). Das ist dann eine Frage der Skalierbarkeit: Bei 10 Treibern ist es egal, bei 10k Treibern essentiell wichtig. Vergleiche die frühen Linux-WLAN-Treiber (mit eigenem Stack, nur unverschlüsselt/WEP) mit den etwas späteren ("SoftMAC" WLAN-Stack, allerdings nicht in den Kernel aufgenommen) und den aktuellen ("mac80211" WLAN-Stack, im Kernel).
Ich behaupte mal das ist ne Design-Frage!? Eine vernünftig designte Schnittstelle sollte nicht verändert werden müssen (soviel zur Theorie ;) ).

Zitat von: svenska
mac80211-Treiber können (mit Ausnahmen) alle WEP, WPA, WPA2, Monitor Mode und Host Mode. Der Stack ist so primitiv (und mächtig), dass eventuelle WEP-Hardware nicht genutzt werden kann - allerdings kann dadurch jede Karte WPA2. Die Arbeit wird dem Treiber abgenommen und in der CPU erledigt.
Wenn ich das richtig verstanden habe, dann wird die gesamte Verschlüsselung in Software gemacht? Die Idee gefällt mir.
Wenn man das richtig anstellt, sollte es sogar so funktionieren, das der Treiber eventuell vorhande Hardwarefeatures nutzt und der Rest wird per Software gemacht (ungefähr wie bei OpenGL/DirectX).

Zitat von: svenska
Ich meinte: Dein Treiber sei jetzt perfekt und optimal. Dann stolpert er über nicht-perfekte Hardware.

Das eine (perfekter Treiber) widerspricht dem anderen (perfekte Hardware). Also entsteht eine Mischung aus try&error, whitelists, blacklists und Workarounds.

Damit musst du leben und wenn du dir über sowas beim Design einen Kopf machst, kann es nur leichter werden.
Ich sags mal so, wenn eine CPU irgendeinen Fehler hat (z.B. bestimmte Pentium-Bugs) und die noch nicht bekannt sind. Dann kannst du erstmal gar nichts machen, weil der Kernel nicht läuft.
Ist der Fehler dann bekannt samt nen Work-Around, kannst du diesen in deinen Kernel einbauen.

Genauso würde ich dann bei einem "perfekten" Treiber vorgehen. Hat die Hardware nen Fehler funktioniert der Treiber und damit das System nicht. Denn wenn der Fehler (wie in deinem Bsp.) in einem generischen Treiber liegt und du keinen speziellen hast, läuft dein OS halt auf der Hardware nicht. Erst wenn du nen Work-Around drin hast läuft es dann.
Sehe da jetzt nicht so das Problem. Sowas musste ich schon oft in meinem Bootloader machen, wegen irgendwelchen BIOS-Sachen, die schlecht bis gar nicht dokumentiert sind.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #36 am: 24. September 2010, 16:24 »
Hallo,

Zitat von: svenska
Legst du die Treiberschnittstelle fest, dann bist du gezwungen, sie kompatibel zu halten und (wenn sich deine Schnittstelle als unzureichend erweist) musst dann parallel mehrere dieser Schnittstellen anbieten (können). Das ist dann eine Frage der Skalierbarkeit: Bei 10 Treibern ist es egal, bei 10k Treibern essentiell wichtig.
Ich behaupte mal das ist ne Design-Frage!? Eine vernünftig designte Schnittstelle sollte nicht verändert werden müssen (soviel zur Theorie ;) ).
Erschwerend kommt hinzu, dass sich Hardware verändert. Wieder ein Beispiel: Eine Grafikkarte lässt sich recht einfach als simpler 2D-Framebuffer abstrahieren, eventuell mit ein paar Beschleunigungsfunktionen (BitBlt, Transparenz, YUV-Overlay). Betrachtest du aber eine heutige Grafikkarte, dann findest du CUDA, 3D-Matritzenfunktionen und viel mehr. Daher lässt sich eine 3D-Grafikkarte auch (und recht sinnvoll) als programmierbare Shadereinheit abstrahieren, bei der du den 2D-Anteil als Textur betrachtest. Genau das geschieht derzeit in Linux mittels Gallium3D.

Die jetzigen Ergebnisse sehen gut aus: Software-Rendering ist wesentlich schneller als vorher, die API ist nicht OpenGL-zentrisch, sondern es gibt auch einen nativen Direct3D 10/11 State Tracker, man kann es für Video-Dekodierbeschleunigung und Vektorgrafiken verwenden. Und es geht auf jeder Grafikkarte mit modernen Shadern. Außerdem benutzt keine moderne GUI mehr die beschleunigten Funktionen wie Rechtecke/Musterzeichnen/... und für Schatten ist das alles suboptimal.

Das eine lässt sich auf das andere nicht oder nur schlecht abbilden und daher muss so eine Abstraktion auch mal geändert werden. Plus: Eine perfekte Abstraktion denke ich mir nicht aus und du wahrscheinlich auch nicht. :-P

Zitat von: svenska
mac80211-Treiber können (mit Ausnahmen) alle WEP, WPA, WPA2, Monitor Mode und Host Mode. Der Stack ist so primitiv (und mächtig), dass eventuelle WEP-Hardware nicht genutzt werden kann - allerdings kann dadurch jede Karte WPA2. Die Arbeit wird dem Treiber abgenommen und in der CPU erledigt.
Wenn ich das richtig verstanden habe, dann wird die gesamte Verschlüsselung in Software gemacht? Die Idee gefällt mir.
Grundsätzlich ja. Da die Hersteller gemerkt haben, dass WEP schlecht war und sich jetzt nicht trauen (müssen), eine Verschlüsselung in Hardware zu gießen, wird bei modernen WLAN-Chipsätzen die gesamte Crypto eh im Treiber gemacht.

Wenn man das richtig anstellt, sollte es sogar so funktionieren, das der Treiber eventuell vorhande Hardwarefeatures nutzt und der Rest wird per Software gemacht (ungefähr wie bei OpenGL/DirectX).
Ja. Das setzt aber auch wieder voraus, dass du die Hardware sinnvoll abstrahiert hast, um eben solche Fähigkeiten dann auch wieder feststellen und ausnutzen zu können. Schließlich muss DirectX alle von der Hardware unterstützten Funktionen auch anbieten, um sie als Software-Fallback anbieten zu können.

Ich sags mal so, wenn eine CPU irgendeinen Fehler hat (z.B. bestimmte Pentium-Bugs) und die noch nicht bekannt sind. Dann kannst du erstmal gar nichts machen, weil der Kernel nicht läuft.
Ist der Fehler dann bekannt samt nen Work-Around, kannst du diesen in deinen Kernel einbauen.
Naja, der Kernel wird wahrscheinlich schon laufen. Aber vielleicht wird dein Scheduler unglaublich langsam oder einmal die Woche schmiert ein Prozess ab und keiner weiß warum. Oder (Pentium-Bug) die Winkelfunktionen im Coprozessor sind kaputt. Dein Kernel nutzt nur Ganzzahlarithmetik, deine Anwendung macht aber Floating-Point Cast-Auf-Int Zeigerarithmetik und stürzt ab. Sowas merkt man nicht

Genauso würde ich dann bei einem "perfekten" Treiber vorgehen. Hat die Hardware nen Fehler funktioniert der Treiber und damit das System nicht. Denn wenn der Fehler (wie in deinem Bsp.) in einem generischen Treiber liegt und du keinen speziellen hast, läuft dein OS halt auf der Hardware nicht. Erst wenn du nen Work-Around drin hast läuft es dann.
Der generische Treiber ist aber fehlerfrei (so die Annahme). Und die Probleme sind sehr subtil. Wobei es generische Treiber auch meistens nicht trifft, weil die meist andere (alte, stabile, getestete) APIs benutzen: Aber es trifft zum Beispiel den rtl8187b, der mit deinem Treiber für rtl8187 nicht (oder nur schlecht) funktioniert.[/quote]

Ist auch kein Problem, man sollte nur halt mal drüber nachgedacht haben.

Gruß,
Sebastian

 

Einloggen