Fonctionnement d'un ordinateur/La mémoire virtuelle des périphériques

Les périphériques modernes incorporent de la mémoire. Un exemple classique est la mémoire vidéo, intégrée aux cartes graphiques modernes. La mémoire intégrée au périphérique est mappée en mémoire, en détournant suffisamment d'adresses mémoires normales. Elle est ainsi accessible par le processeur. En théorie, elle est censée être mappée en mémoire physique, et donc accessible seulement en espace noyau. Mais dans d'autres cas, elle est mappée dans l'espace d'adressage virtuel du processeur, dans la portion allouée au noyau.

De plus, beaucoup de périphériques modernes intègrent un processeur dans leurs circuits : cartes graphiques, cartes sons, etc. Le processeur intégré exécute des programmes dédiés, souvent fournis par les pilotes du périphérique ou le système d'exploitation, parfois par des applications spécialisées. Cela peut paraitre bizarre, mais sachez que c'est exactement ce qui se passe pour votre carte graphique si celle-ci a moins de vingt ans. Les shaders des jeux vidéos, exécutés par le processeur de la carte graphique, en sont un bon exemple).

Et ces processeurs peuvent gérer la mémoire virtuelle, ils disposent de mécanismes de traduction d'adresse comme la pagination ! L'utilité et le fonctionnement de la mémoire virtuelle liée aux périphériques sera l'objet de ce chapitre. Dans ce qui va suivre, nous allons faire la distinction entre la mémoire virtuelle du processeur et celle des périphériques. Pour bien appuyer cette distinction, nous parlerons de CPU-VM pour la première, d'IO-VM pour la dernière.

L'intérêt de l'IO-VM pour les périphériques

modifier

L'avantage principal de l'IO-VM se manifeste sur les périphériques qui incorporent un processeur et une mémoire RAM. Sans mémoire virtuelle, ce processeur n'accède qu'à la mémoire du périphérique, rien de plus. Son espace d'adressage est prévu pour coller parfaitement à la mémoire RAM installée sur le périphérique. Mais avec l'IO-VM, le processeur intégré au périphérique peut aussi utiliser la RAM de l'ordinateur. Pour ne pas confondre les deux, nous allons parler de mémoire locale pour la RAM installée sur le périphérique, de mémoire système pour la RAM de l'ordinateur. L'intérêt de l'IO-VM est que le périphérique peut déborder sur la mémoire système si sa mémoire locale est pleine.

Un bon exemple est celui des cartes graphiques dédiées modernes. L'IO-VM des GPUs dédiés permet d'utiliser plus de RAM qu'il n'y en a d'installé sur la carte graphique. Par exemple, si on prend une carte graphique avec 6 gigas de RAM dédiée, elle pourra gérer jusqu'à 8 gigas de RAM : les 6 en mémoire vidéo, plus 2 gigas fictifs en rab. Et c'est là qu'intervient la première différence avec la CPU-VM : les 2 gigas fictifs ne sont pas stockés sur le disque dur dans un fichier pagefile, mais sont dans la mémoire système. Pour le dire autrement, ces cartes dédiées peuvent utiliser la mémoire système si jamais la mémoire vidéo est pleine.

 
Mémoire virtuelle des cartes graphiques dédiées

L'espace d'adressage du processeur et du périphérique peuvent être unfiés ou séparés. Pour les cartes graphiques, des standards comme l'Heterogeneous System Architecture permettent au processeur et à une carte graphique de partager le même espace d'adressage. Une adresse mémoire est donc la même que ce soit pour le processeur ou la carte graphique.

Mémoire vidéo dédiée Mémoire vidéo unifiée
Sans HSA    
Avec HSA    

Le lien entre IO-VM et contrôleur DMA

modifier

Le DMA permet aux périphériques modernes, notamment les cartes graphiques, d'accéder à la mémoire RAM et de l'utiliser. Et cela doit prendre en compte la mémoire virtuelle. Les périphériques anciens utilisaient des adresses physiques, à savoir qu'ils adressaient la mémoire RAM directement, sans passer par une traduction d'adresse. Mais les périphériques modernes prennent en compte la mémoire virtuelle et utilisent des adresses virtuelles.

L'usage de l'IO-VM permet de passer outre les limitations d'adressage du contrôleur DMA. Le contrôleur DMA peut gérer des adresses virtuelles très courtes, qui sont traduites en adresses physiques longues, grâce à des techniques d'extension d'espace d'adressage. Le résultat est que l'on peut se passer de tampons DMA.

Un autre avantage est que l'on peut communiquer avec un périphérique DMA sans avoir à allouer des blocs de mémoire contiguë. Avec la pagination, un bloc de mémoire transféré via DMA peut être éclaté sur plusieurs pages séparées et dispersées en mémoire RAM. Le bloc de mémoire est contiguë dans l'espace d'adressage, mais éclaté en mémoire physique.

Un dernier avantage est que les échanges entre processeur et périphérique sont sécurisés. La mémoire virtuelle des périphériques incorpore des mécanismes de protection mémoire. Grâce à eux, le périphérique ne peut pas accéder à des régions de la mémoire auquel le pilote de périphérique ne lui a pas donné accès. Une erreur de configuration ou de programmation ne permet pas au périphérique d'accéder à des régions mémoire protégées, qui ne lui sont pas allouées. Des tentatives de hacking basée sur des attaques DMA ne marchent plus avec ce type de mémoire virtuelle.

L'implémentation de la mémoire virtuelle pour les périphériques

modifier
 
Les périphériques peuvent eux aussi utiliser la mémoire virtuelle. Dans ce cas, ceux-ci intègrent une MMU dans leurs circuits. Ces MMU, aussi appelées IOMMU, sont séparées de la MMU du processeur.

Pour faire la traduction d'adresse, les périphériques incorporent une MMU dédiée, la IOMMU qui s'occupe de traduire les adresses utilisées par les périphériques en adresses physiques à destination de la mémoire. Ils intègrent aussi des page table walkers, des TLBs et tout ce qui va avec l'incorporation de la mémoire virtuelle. Par exemple, les cartes graphiques modernes sont couplés à une MMU apelée la Graphics address remapping table, abrévié en GART. Cela vaut aussi bien pour les cartes graphiques utilisant le bus AGP que pour celles en PCI-Express.

La IOMMU n'est pas dans le périphérique proprement dit, il arrive qu'elle soit intégrée au chipset de la carte mère, voire dans le processeur. La IOMMU est connectée au bus mémoire directement, comme une MMU normale. Il n'est pas rare qu'elle soit partagée entre tous les périphériques, ou du moins avec plusieurs d'entre eux. Typiquement, il y a une IOMMU par bus. Ce faisant, plusieurs périphériques se partagent un même espace d'adressage, s'ils sont reliés au même bus, à la même IOMMU.

Généralement, les périphériques utilisent la pagination, pas la segmentation. Et qui dit pagination dit table des pages. Les périphériques DMA modernes ont leur propre table des pages dédiée, placée en mémoire RAM. Généralement, elle est séparée des autres tables des pages. En théorie, chaque accès à la table des pages demande d'accéder à la RAM, et donc de lancer une requête qui passe par le bus. Par exemple, une carte graphique devrait passer par le bus PCI-Express à chaque accès mémoire. Dans les faits, les périphériques incorporent des TLB, des caches qui mémorisent des correspondances adresses logique-physique, pour éviter d'accéder à la RAM fréquemment.

Un accès mémoire se passe comme suit. Le périphérique effectue un accès mémoire et accède à la TLB. Si l'entrée de la table des pages est dans la TLB, la TLB renvoie l'adresse physique à lire et l'accès mémoire se poursuit. Cependant, si la correspondance voulue n'est pas trouvée dans la TLB, le périphérique envoie une requête à l'IOMMU, via le bus PCI-Express. La IOMMU accéde alors à la table des pages, grâce à des page table walkers. En cas de succès de page, elle renvoie l'entrée de la table des pages demandée au périphérique, via le bus. Mais en cas de défaut de page, l'IOMMU échange des informations avec le périphérique PCI-Express, puis déclenche une interruption de défaut de page sur le processeur. Le système d'exploitation gére le défaut de page, puis la IOMMU reprend le relai et gère un succès de page.