webentwicklung-frage-antwort-db.com.de

Wie erkennt man crc32 auf aarch64

Kann ein user -Programm auf aarch64 erkennen, ob crc32-Anweisungen verfügbar sind? Ich habe Hinweise auf die Kernelunterstützung gefunden für eine solche Erkennung, was bedeutet, dass die Register mit den Informationen darüber, welche Anweisungen im Benutzermodus funktionieren, im Benutzermodus (!) Nicht verfügbar sind.

Ist das der Fall? Oder gibt es eine tragbare Methode, um festzustellen, ob die crc32-Anweisungen verfügbar sind?

Hinweis: Was ich unter "Benutzerprogramm" und "tragbar" verstehe, ist ein Ansatz, der weder privilegierte Anweisungen noch betriebssystemspezifische Aufrufe oder Dateien (z. B./proc/cpuinfo) erfordert. Der Code selbst muss in der Lage sein, zu ermitteln, ob die Anweisungen verfügbar sind, und sie zu verwenden, wenn sie vorhanden sind, oder auf eine Alternative zurückzugreifen, falls dies nicht der Fall ist. Beispielsweise haben Intel-Prozessoren die Anweisung cpuid für diesen Zweck.

Update:

In den Architekturbeschreibungen von ARM habe ich ein Benutzerregister PMCR_EL0 gefunden, das einen 8-Bit-Implementierercode und einen 8-Bit-ID-Code für den Prozessor bereitstellt. Wenn ich eine Liste dieser Codes finden könnte, bin ich vielleicht näher an dem, was ich suche.

Update 2:

Wenn ich jedoch versuche, dieses Register zu lesen, erhalte ich eine illegale Anweisungsausnahme. Also benötigen auch EL0-Register einen privilegierten Zugriff?

4
Mark Adler

Nicht nach meinem besten Wissen.

Die Art und Weise, wie ich es in Chromiums zlib implementiert habe, war die Verwendung der verfügbaren Betriebssystemfunktionalität: https://cs.chromium.org/chromium/src/third_party/zlib/arm_features.c?l=29

Es ist auch wichtig zu erwähnen, dass die crc32-Anweisungen in ARMv8 Teil der Crypto-Erweiterungen sind, die für ARMv8 optional und für ARMv8-1 obligatorisch sind. Dies bedeutet auch, dass eine Laufzeit-Feature-Erkennung erforderlich ist. Weitere Informationen finden Sie hier: https://cs.chromium.org/chromium/src/third_party/zlib/BUILD.gn?l=64

Ich würde es vermeiden, direkt aus/proc/cpuinfo zu lesen, da dies in manchen Kontexten möglicherweise nicht verfügbar ist (da es je nach Android-Variante auch falsch negativ sein kann). 

In Chromium wird zlib sowohl in einem privilegierten Kontext (d. H. Teil des Netzwerkcodes im Haupt-Browser-Prozess) als auch in einem Sandkasten-Kontext (d. H. Teil des Renderer-Prozesses in einer Registerkarte) ausgeführt. Im RendererProcess sollte das Lesen aus/proc/cpuinfo fehlschlagen.

Ein Vorschlagshammer-Ansatz besteht darin, einen Signal-Handler zu installieren und die Anweisung mit Inline-asm auszuführen. Dies würde einen Fehler verursachen, wenn die Anweisung nicht verfügbar ist (und vom Handler erfasst werden könnte). Nicht zu empfehlen.

Das oben erwähnte Beispiel ( https://github.com/torvalds/linux/blob/master/Documentation/arm64/cpu-feature-registers.txt ) funktionierte auf einer von mir getesteten 1 ARM - Platine ( MachiatoBin) scheiterte aber an zwei anderen (rock64 und nanopi m4).

Der in Chromium implementierte Ansatz funktioniert auf allen Platinen (auch einige Mobiltelefone, die ich getestet habe).

Ein weiteres Detail von getauxval: Das korrekte Flag ändert sich, wenn es mit 32 oder 64 Bit läuft. In 64Bits wäre das also HWCAP_CRC32, in 32Bit wäre es HWCAP2_CRC32.

Über den sledgehammer -Ansatz: Signale sind anfällig für Race-Bedingungen, und Sie würden sich weiterhin auf die Verwendung von betriebssystemspezifischen APIs verlassen (d. H. Zur Installation des Signalhandlers).

Wenn eine gegebene Task abstürzt (auch wenn dies konstruktiv und vom Ausführungskontext isoliert ist), werden abhängig vom Kontext rote Flags ausgelöst.

Dies ist ein Punkt (d. H. Featureerkennung), an dem das Leben auf x86 wesentlich einfacher ist.

Davon abgesehen kann es ein akzeptabler Kompromiss sein, sich auf die Betriebssystemfunktionen zu verlassen. Wir haben den verlinkten Code in Chromium seit dem Release M66 (derzeit stabil ist M72) ausgeliefert, das vor fast einem Jahr ohne kritische Berichte gelandet ist.

Eine Überlegung unter Android war, dass das NDK intern Android_getCpuFeatures () mithilfe von dlopen ()/dlsym () implementieren kann und dass dies beim ersten Start 500us zu 1000us hinzufügen kann, weshalb das Ergebnis der CPU-Funktionserkennung zwischengespeichert wird.

Eine weitere Überlegung für Multithread-Apps (wie Chromium) war die Notwendigkeit einer Thread-Barriere (d.h.

Update: Die ursprüngliche Antwort beantwortete die Frage nicht, da der Autor einen universellen Teil des Codes wollte, der auf EL0 ausgeführt werden kann, um festzustellen, ob die CRC32-Funktion vorhanden ist oder nicht, ohne dass Anforderungen an das Betriebssystem oder die Bare-Metal-Umgebung gestellt werden.

Ich verstehe, dass ein solcher Code auf ID_AA64ISAR0_EL1 zugreifen muss, und weil auf EL0 ausgeführter Code nicht darauf zugreifen kann, wäre ohnehin ein Wechsel zu einer privilegierteren Ausnahmestufe erforderlich.

Auf die gleiche Weise würde das Abfangen einer illegalen Anweisung unter Verwendung eines "tragbaren" Codeabschnitts den Zugriff auf ein VBAR_ELx-Register erforderlich machen. Dies kann nicht mit einem auf EL0 laufenden Programm erreicht werden, das nicht auf einem zugrunde liegenden Betriebssystem/privilegierten Monitor basiert.

Daher meine Antwort auf die Frage "Ist das der Fall?" wäre: Ja, es ist ein tragbarer/universeller Codeabschnitt, der auf EL0 ausgeführt wird, und kann nicht feststellen, ob die CRC32-Funktion verfügbar ist oder nicht.

Der Beispielcode in der Dokumentation referedced in der Frage funktioniert jedoch gut auf einem Expressobin, der aarch64 linux 4.14.80 ausführt, und sollte aus den in der Kernel-Dokumentation beschriebenen Gründen der Verwendung von getauxval () vorgezogen werden .

1
Frant

dies ist möglicherweise nicht direkt zugänglich. ARM würde Spezifikationen für jeden Prozessor bereitstellen - daher besteht die Möglichkeit, ein Diagramm zu erstellen, mit dem CPU-Funktionen anhand des Modellnamens nachgeschlagen werden können ./proc/cpuinfo ist Linux-spezifisch. Bei Windows wäre das Äquivalent WMI; OSX läuft nicht auf ARM (soweit ich weiß). Wenn es sich nicht um ein Typ-1-Hypervisier handelt, das das Betriebssystem vollständig umgeht, muss betriebssystemspezifischer Code vorhanden sein (und der Benutzer kann auch VT deaktivieren).

0
Martin Zeitler