web-dev-qa-db-fra.com

Comment détecter crc32 sur aarch64

Est-il possible qu'un programme user sur aarch64 détecte si des instructions crc32 sont disponibles? J'ai trouvé des références au support du noyau pour une telle détection, ce qui implique que les registres contenant les informations sur les instructions qui fonctionneront en mode utilisateur ne sont pas disponibles en mode utilisateur (!).

Est-ce le cas? Ou existe-t-il un moyen portable de déterminer si les instructions crc32 sont disponibles?

Remarque: ce que j'entends par "programme utilisateur" et "portable" est une approche qui ne nécessite pas d'instructions privilégiées ni d'appels ou de fichiers spécifiques au système d'exploitation (par exemple,/proc/cpuinfo). Le code lui-même doit pouvoir détecter si les instructions sont disponibles et les utiliser si elles sont, ou utiliser une alternative si elles ne le sont pas. Par exemple, les processeurs Intel ont l'instruction cpuid à cette fin.

Mettre à jour:

En parcourant les descriptions d'architecture ARM, j'ai trouvé un registre de niveau utilisateur, PMCR_EL0, qui fournit un code de mise en œuvre sur 8 bits et un code d'identification sur 8 bits pour le processeur. Si je pouvais peut-être trouver une liste de ces codes, je serais peut-être plus proche de ce que je cherchais.

Mise à jour 2:

Cependant, lorsque j'essaie de lire ce registre, j'obtiens une exception d'instruction illégale. Ainsi, même les registres EL0 nécessitent un accès privilégié?

4
Mark Adler

Pas au meilleur de ma connaissance.

La façon dont je l'ai implémenté dans zlib de Chromium utilisait les fonctionnalités disponibles du système d'exploitation: https://cs.chromium.org/chromium/src/third_party/zlib/arm_features.c?l=29

Il est également pertinent de mentionner que les instructions crc32 sur ARMv8 font partie des extensions de chiffrement facultatives sur ARMv8 et obligatoires sur ARMv8-1. Cela signifie également que la détection des fonctionnalités d'exécution est nécessaire. Pour plus de détails, veuillez vérifier: https://cs.chromium.org/chromium/src/third_party/zlib/BUILD.gn?l=64

J'éviterais de lire directement à partir de/proc/cpuinfo, car cela pourrait ne pas être disponible dans certains contextes (car, selon la version d'Android, cela pourrait être un faux négatif). 

Dans Chromium, zlib sera exécuté à la fois dans un contexte privilégié (c'est-à-dire une partie du code de réseau dans le processus de navigateur principal) et également dans un contexte en bac à sable (c'est-à-dire une partie du processus de rendu dans un onglet). Dans RendererProcess, la lecture de/proc/cpuinfo devrait échouer.

Une approche par sledgehammer consisterait à installer un gestionnaire de signaux et à exécuter l'instruction avec asline en ligne, ce qui provoquerait une erreur si l'instruction n'est pas disponible (et pourrait être capturée par le gestionnaire). Non recommandé, cependant.

L'exemple susmentionné ( https://github.com/torvalds/linux/blob/master/Documentation/arm64/cpu-feature-registers.txt ) a fonctionné sur 1 carte ARM que j'ai testée ( MachiatoBin) mais a échoué dans 2 autres (rock64 et nanopi m4).

L'approche implémentée dans Chromium fonctionne sur toutes les cartes (ainsi que sur quelques téléphones portables que j'ai testés).

Un autre détail à propos de getauxval: le drapeau correct changera s’il fonctionne sur 32 bits ou 64 bits. Donc, dans 64 bits, ce serait HWCAP_CRC32, alors que dans 32 bits, ce serait HWCAP2_CRC32.

À propos de l’approche sledgehammer: les signaux sont sujets aux conditions de concurrence. De plus, vous devez toujours utiliser des API spécifiques au système d’exploitation (c’est-à-dire installer le gestionnaire de signaux).

Enfin, en fonction du contexte, si une tâche donnée échoue (même si elle est conçue et isolée du contexte d’exécution), des indicateurs d’alerte seront déclenchés.

C’est un point (c’est-à-dire la détection de caractéristiques) où la vie est beaucoup plus facile sur x86.

Cela étant dit, le recours aux fonctionnalités du système d'exploitation peut constituer un compromis acceptable. Nous livrons le code lié en chrome depuis la version M66 (la version stable actuelle est M72), qui a atterri pour la première fois il y a presque un an sans aucun problème.

Une considération sur Android était que le NDK pouvait implémenter en interne Android_getCpuFeatures () en utilisant dlopen ()/dlsym () et qu’il pouvait ajouter environ 500 à 1000 au premier démarrage, c’est pourquoi nous mettons en cache le résultat de la détection des fonctionnalités du processeur.

Une autre considération pour les applications multithreads (telles que Chromium) était la nécessité d’une barrière de thread (c’est-à-dire pthread_once_t) pour éviter les situations de concurrence lors de la détection des fonctionnalités du processeur.

2

Mise à jour: la réponse d'origine ne répondait pas à la question car son auteur souhaitait une partie universelle du code s'exécutant à EL0, capable de déterminer si la fonctionnalité CRC32 est présente ou non, sans aucune exigence du système d'exploitation ou de l'environnement nu-métal utilisé.

D'après ce que je comprends, un tel code devrait accéder à ID_AA64ISAR0_EL1 et, comme le code exécuté en EL0 ne peut y accéder, un passage à un niveau d'exception plus privilégié serait de toute façon requis.

De la même manière, intercepter une instruction illégale à l'aide d'une section de code 'portable' nécessiterait l'accès à un registre VBAR_ELx, ce qui ne peut pas être réalisé à partir d'un programme exécuté sur EL0 qui ne s'appuie sur aucun système d'exploitation/moniteur privilégié sous-jacent.

Par conséquent, ma réponse à la question "Est-ce le cas?" Oui, c’est-à-dire qu’une section de code portable/universelle fonctionnant à EL0 ne peut pas déterminer si la fonctionnalité CRC32 est disponible ou non.

Ceci étant dit, l'exemple de code fourni dans la documentation référencée dans la question fonctionne correctement sur un Expressobin exécutant aarch64 linux 4.14.80 et devrait être préféré à l'utilisation de getauxval () pour les mêmes raisons que celles expliquées dans la documentation du noyau. .

1
Frant

cela pourrait ne pas être directement accessible; mais ARM fournirait spécifications pour chaque processeur - il est donc possible de créer un graphique, qui peut être utilisé pour rechercher les fonctionnalités de la CPU par le nom de modèle ./proc/cpuinfo est spécifique à Linux; l'équivalent Windows serait WMI; OSX ne fonctionne pas sur ARM (pour autant que je sache). sauf s'il s'agit d'un hyper-viseur de type 1, qui contourne entièrement le système d'exploitation, il doit exister un code spécifique au système d'exploitation (et l'utilisateur peut également désactiver VT).

0
Martin Zeitler