La Fondation de la Communication Processeur-Périphérique

Pour un ingénieur logiciel qui écrit un code de haut niveau, lire d'une adresse mémoire ou écrire à une variable est une opération atomique simple. Cependant, cette simplicité masque un mécanisme matériel sophistiqué qui est fondamental pour tout calcul moderne. La capacité d'un processeur à contrôler un disque dur, afficher une image sur un écran ou recevoir un paquet d'une carte réseau dépend entièrement de la relation complexe entre deux concepts fondamentaux : registres du processeur et soutien de mémoire I/O (MMIO).Les registres fournissent le stockage temporaire à grande vitesse nécessaire au calcul, tandis que MMIO agit comme pont, cartographiant les interfaces de contrôle des périphériques dans l'espace d'adresse mémoire standard du système.

La microarchitecture des registres CPU

Les registres représentent le niveau de mémoire le plus élevé de la hiérarchie de stockage, situé directement dans le noyau du processeur. Ils sont la mémoire de travail du processeur, contenant les données immédiates, les adresses et les informations de contrôle nécessaires pour exécuter les instructions. Contrairement aux types de mémoire plus lents tels que DRAM ou NAND flash, les registres sont construits à l'aide de cellules RAM statiques rapides (SRAM) ou de flip-flops et sont conçus pour un accès à un cycle à la fréquence de l'horloge du CPU.

Registres et voies d'exécution des objectifs généraux

Dans les architectures comme ARM64 (AArch64), le programmeur a accès à 31 registres à usage général (X0-X30). Ces registres sont la source et la destination exclusives des opérations d'unités logiques arithmétiques (ALU). Lorsque le processeur exécute une instruction comme , les valeurs stockées dans les registres physiques X1 et X2 sont lues, transmises à l'ALU, et le résultat est réécrit pour enregistrer X0. Ce couplage étroit entre les registres et les unités d'exécution définit l'architecture de la charge-stockage [ qui prévaut dans les processeurs modernes. Les données doivent être chargées de mémoire dans un registre avant qu'il puisse être manipulé, et le résultat doit être ré stocké.

Registres spéciaux et contrôle du système

Au-delà des GPR, un processeur se base sur une suite de registres à usage spécial pour maintenir l'état et gérer le flux d'exécution. Ceux-ci sont souvent invisibles au code de niveau application mais sont constamment accessibles par le système d'exploitation et le firmware.

  • Contrôle de programme (PC):[ Ce registre contient l'adresse mémoire de l'instruction d'exécution en cours. Il est automatiquement incrémenté et peut être modifié par des instructions de branche.
  • Stack Pointer (SP):[ Utilisé pour gérer la pile d'appels, contenant l'adresse du haut du cadre de la pile actuelle. Il est critique pour les appels de fonction et le stockage de variables locales.
  • Statut Register (PSR / FLAGS):[ Stocke les codes d'état résultant des opérations ALU, tels que zéro, transport, débordement et négatif. Ces drapeaux contrôlent les instructions de branche conditionnelle et sont essentiels pour la mise en œuvre des boucles et des énoncés .
  • Link Register (LR) / X30: Dans les architectures ARM, ce GPR spécial détient l'adresse de retour pour un appel de fonction, permettant une invocation efficace sous-routine sans avoir à pousser l'adresse de retour à la pile immédiatement.

Gestion moderne du registre : Rénovation et spéculation

Dans les processeurs modernes hors-commande, le fichier de registre physique est significativement plus grand que le fichier architectural spécifié par l'architecture de l'ensemble d'instructions (ISA). Le CPU utilise une technique appelée register renameting[ pour surmonter les risques de données. Par exemple, si un compilateur réutilise le registre architectural X0 pour plusieurs valeurs non reliées, le matériel cartographiera ces références logiques à des registres physiques uniques. Cela permet au CPU d'exécuter des instructions en parallèle même lorsque l'ISA suggère une dépendance séquentielle. Bien que cette complexité soit transparente pour le logiciel, elle souligne le rôle critique que jouent les registres dans le maintien d'un débit d'instruction élevé, et elle affecte directement la la latence de l'accès MMIO lorsque des effets secondaires sont impliqués.

Les fondamentaux des E/S maquillés en mémoire (MMIO)

Les E/S mémorisés sont une méthodologie matérielle où les registres de contrôle et de données des périphériques sont assignés des adresses dans la carte mémoire standard du processeur. Au lieu d'utiliser des instructions d'E/S dédiées (comme dans l'architecture x86 IN/OUT), MMIO permet au processeur d'interagir avec les périphériques en utilisant des instructions de charge standard (LDR) et de stockage (STR).

L'architecture spatiale d'adresse unifiée

Dans un système MMIO, l'espace d'adresse physique est partagé entre les registres système RAM, ROM/flash et périphérique. Une gamme spécifique d'adresses est réservée aux registres de périphériques. Lorsque le CPU émet une instruction de chargement ou de stockage à une adresse dans cette gamme réservée, le bus mémoire décode l'adresse et conduit la transaction vers le bus périphérique approprié (comme AMBA AXI ou PCI Express) plutôt que vers le contrôleur mémoire.

Par exemple, sur un microcontrôleur ARM Cortex-M typique, la carte mémoire est strictement appliquée : les adresses de à sont réservées au code, à à à à sont réservées exclusivement aux périphériques. Ce cloisonnement permet au tissu de bus de définir des autorisations d'accès strictes et des caractéristiques de synchronisation pour chaque région.

Comparaison des I/O (MPIO) et des I/O (port-mappered)

L'alternative à MMIO est l'isolement des E/S ou des E/S à portage (PMIO), utilisé historiquement par l'architecture x86. PMIO utilise des broches matérielles et des instructions spéciales (IN/OUT) pour accéder à un espace d'adresse d'E/S séparé.

  • MMIO Avantages: Il réutilise la pleine puissance de l'ensemble d'instructions mémoire du CPU. Vous pouvez utiliser le pointeur déréférencement en C/C++, appliquer des opérations bit-field et utiliser tous les modes d'adressage. MMIO n'a pas besoin de mécanismes de protection spéciaux d'E/S au-delà de l'unité de gestion de mémoire existante (MMU).
  • PMIO Avantages: Il ne consomme pas d'espace d'adresse précieux de la carte mémoire. L'espace d'E/S dédié fournit une séparation nette entre la mémoire de données et les registres de contrôle, qui peut simplifier la conception matérielle dans certains systèmes existants. Cependant, les E/S basés sur port ont généralement un débit inférieur et ne peuvent pas être utilisés pour les transferts mémoire-burst.

Les systèmes modernes x86 utilisent toujours le PMIO pour la compatibilité des appareils existants (p. ex. contrôleur de clavier PS/2), mais les appareils à haute performance comme les GPU et les SSD NVMe dépendent exclusivement du MMIO via le bus PCI Express.

Accès aux registres des appareils à partir du code de haut niveau

Lorsque vous écrivez des pilotes de périphériques en C ou C++, l'accès aux registres MMIO nécessite une sémantique spécifique pour empêcher les optimisations du compilateur de rompre l'interaction matérielle. Le mot clé est essentiel. Il indique au compilateur que la valeur à l'adresse peut changer sans la connaissance du compilateur (par exemple, en raison de changements d'état matériel) et que l'écriture à l'adresse ne doit pas être optimisée. Par exemple : . Sans la qualification , un compilateur peut optimiser un sondage en boucle pour un bit d'état en une lecture unique, ce qui fait que le logiciel est accroché.

La confluence des registres et MMIO

Le vrai « jeu » se produit chaque fois qu'un programme a besoin d'envoyer des données à un périphérique ou de recevoir des données de celui-ci. Le processus implique le déplacement des données entre les registres CPU et les registres de dispositifs MMIO en utilisant des instructions de chargement/stockage, mais les implications matérielles et protocolaires sont uniques.

Charger/Store sémantique sur la mémoire du périphérique

L'exécution d'une instruction comme , où X1 contient l'adresse du registre de données transmis par un appareil, déclenche une séquence spécifique. La valeur du registre général d'utilisation du CPU (W0) est placée sur le bus de données. Le tissu du bus décode l'adresse cible et l'identifie comme une région MMIO. Crucialement, le type de mémoire de cette région est réglé à Strongly Ordered ou Device[ mémoire. Cela empêche le CPU et le bus de lire, de combiner ou de lire des données spéculatives sur ces adresses, car de telles optimisations pourraient entraîner des effets secondaires comme la réinitialisation d'un appareil ou la lecture de données statiques.

Sondage, interruptions et inscriptions des drapeaux d'état

Le schéma d'interaction le plus basique est le sondage. Le CPU lit le registre d'état d'un périphérique (une adresse MMIO) dans un GPR, vérifie un morceau spécifique en utilisant un bitmask et boucle jusqu'à ce que le matériel fixe le drapeau indiquant les données. C'est la forme la plus simple d'interaction mais gaspille les cycles du CPU. Le modèle interrompu est beaucoup plus efficace. Lorsqu'un périphérique a des données, il affirme une ligne d'interruption. Le CPU suspend son thread actuel, lit le registre d'état d'interruption (une autre adresse MMIO) pour trouver la source de l'interruption, puis lit le registre de données.

Accès direct à la mémoire (DMA) et coordination des registres

Pour les appareils à large bande comme les cartes réseau ou les contrôleurs de stockage, le déplacement des données dans les GPR du CPU est prohibitif. Direct Memory Access (DMA) résout cela en permettant au périphérique de transférer directement les données vers la RAM du système sans impliquer le CPU pour chaque mot. Cependant, DMA continue de s'appuyer fortement sur les registres du CPU et MMIO pour sa configuration.

  • Le CPU écrit aux registres MMIO du contrôleur DMA pour définir l'adresse source, l'adresse de destination et la longueur de transfert.
  • Le CPU écrit à un registre de départ MMIO séparé pour lancer le transfert.
  • Pendant que le DMA est en cours, le CPU est libre d'exécuter d'autres codes.
  • Une fois le transfert terminé, le contrôleur DMA écrit à ses propres registres d'état et soulève une interruption. Le CPU doit alors lire ces registres pour vérifier que la transaction a été réussie.

Cette poignée de main, où les registres CPU configurent le système, les moteurs DMA effectuent le levage lourd, et l'état des rapports MMIO enregistre, est l'épine dorsale de haute performance E/S.

Considérations avancées dans les mises en œuvre modernes

À mesure que la complexité du système s'est accrue, plusieurs caractéristiques sophistiquées sont apparues pour gérer les particularités de MMIO et son interaction avec l'état de registre du CPU.

Cohérence de la mémoire et de la cache

Les registres des périphériques sont intrinsèquement non-idéopontes; la lecture d'un registre peut effacer un drapeau d'interruption et l'écriture d'un registre peut démarrer un moteur. Par conséquent, les régions MMIO sont presque toujours marquées comme Inclusibles[ ou Device-nGnRnE[ dans les tables de pages du MMU. Cela force chaque chargement ou stock pour accéder directement au bus, contournant les caches L1 et L2. Cela introduit la latence, car un cache frappé sur une valeur de registre des périphériques statiques pourrait être catastrophique.

MMIO dans PCI Express

Les périphériques PCIe exposent leurs registres de contrôle via MMIO. Pendant le démarrage du système, le firmware ou OS scanne le bus PCIe et assigne les régions de mémoire aux registres d'adresses de base de chaque périphérique. Les BAR définissent la taille et le type de fenêtre MMIO dont l'appareil a besoin. Lorsque le processeur écrit à une adresse dans la BAR d'un périphérique, le complexe racine PCIe convertit la transaction de mémoire en un paquet de couche de transaction PCIe (TLP) et l'oriente vers le paramètre. Cela permet un accès extrêmement élevé aux registres d'appareils, à la mémoire et aux espaces de configuration.

Défis de la virtualisation et OIMMU

Dans les environnements virtualisés, un système d'exploitation invité ne peut pas être donné un accès physique direct aux registres MMIO de l'appareil, car cela briserait l'isolement. L'hyperviseur doit piéger et émuler les accès MMIO de l'invité, qui est lent. Le matériel moderne résout cela avec une Unité de gestion de la mémoire d'entrée-sortie (IOMMU). L'IOMMU se trouve entre l'appareil et le bus mémoire. Il permet à un OS invité de contrôler directement un appareil en mapper les registres MMIO de l'appareil dans l'espace d'adresse virtuelle de l'invité et en traduisant les adresses physiques de l'invité à des adresses réelles de machines pour DMA.

Applications pratiques des registres et de la MMIO

Comprendre ces concepts n'est pas seulement académique. Chaque pilote périphérique écrit pour Linux, Windows ou un RTOS est construit sur cette base.

Récepteur/transmetteur universel asynchrone (UART)

Pour transmettre un caractère, le conducteur doit s'informer d'un registre d'état (MMIO) pour vérifier si le registre de tenue des transmissions (THR) est vide. Il lit cette valeur dans un GPR, teste le bit et les boucles. Une fois le THR vide, le conducteur écrit le caractère à l'adresse THR (MMIO). Cette instruction de stockage unique déplace les données d'un GPR vers le bus et dans le registre de changement de l'UART. Du côté réception, lorsqu'un personnage arrive, l'UART place un bit dans son registre d'état. Le conducteur lit ce registre, voit le drapeau prêt à recevoir et lit le registre tampon pour obtenir l'octet dans un GPR.

Unités de traitement des graphiques (GPU)

Les processeurs GPU sont massivement parallèles et dépendent fortement de MMIO. Le processeur interagit avec le pilote GPU à travers un tampon de sonnerie de commande et un ensemble de registres MMIO. Pour soumettre le travail, le processeur écrit des commandes dans un tampon de sonnerie dans la mémoire du système. Ensuite, il écrit à un registre spécifique MMIO "doorbell" sur le GPU. Ce registre de sonnettes indique au GPU que de nouvelles commandes attendent. Le GPU lit ensuite le tampon de sonnerie via DMA. L'interaction entière est orchestrée par l'écriture CPU à la mémoire et un seul registre MMIO, en tirant parti de l'espace d'adresse pour lancer un traitement parallèle complexe.

Contrôleurs d'interface réseau (NIC)

Les NIC modernes utilisent un principe similaire. Ils ont un ensemble de registres MMIO pour le contrôle et un ensemble de descripteurs anneaux dans la mémoire principale. Lorsqu'un paquet arrive, le NIC utilise DMA pour placer les données du paquet dans un tampon mémoire pré-alloté et écrit le descripteur tampon dans l'anneau. Il met ensuite à jour son propre registre MMIO "pointeur de queue" et soulève en option une interruption. Le pilote CPU utilise MMIO lit pour vérifier les pointeurs de queue mis à jour et détermine quels tampons à traiter. L'efficacité de ce processus dépend entièrement de la capacité du CPU à effectuer des charges cohérentes et à stocker dans l'espace MMIO.

Évaluation des E/S à mémoire

Bien que MMIO soit le paradigme dominant des périphériques modernes, il s'agit d'un compromis de conception avec des avantages et des inconvénients distincts.

Avantages dans la conception du système

MMIO simplifie le modèle de programmation en éliminant un ensemble d'instructions d'entrée/sortie séparé. Il permet une intégration facile avec l'unité de protection mémoire du processeur (MMU) et permet l'utilisation du code C standard pour le développement du pilote. Il s'adapte bien aux périphériques à haut débit, car DMA peut être facilement coordonné par des anneaux de descripteurs à base de mémoire.

Inconvénients et pièges potentiels

Un inconvénient important est la consommation d'espace d'adresse physique. Sur les systèmes 32 bits, la dédicace d'un large éventail d'espace d'adresse aux périphériques inutilisés ou lents peut fragmenter la carte mémoire. De plus, l'accès MMIO est intrinsèquement séquentiel et introuvable, ce qui le rend plus lent que l'accès aux données en cache. Un bug commun dans le développement du pilote manque le mot clé , qui provoque des optimisations compilateurs pour briser l'accès matériel.

La relation symbiotique dans l'architecture du système

L'interaction entre les registres du processeur et les E/S mactées par mémoire est la sympathie mécanique qui conduit à l'ensemble de l'informatique. Les registres fournissent la vitesse de cloque et la manipulation immédiate des données requises par le processeur, tandis que MMIO fournit l'interface standardisée et flexible nécessaire pour interagir avec le monde physique des périphériques. Que le développeur écrive un simple à un UART, initialisant un pipeline GPU complexe, ou déployant un serveur virtualisé, ils comptent sur cette relation matérielle fondamentale.