Fonctionnement d'un ordinateur/L'espace d'adressage du processeur
L'espace d'adressage du processeur correspond à l'ensemble des adresses utilisables par le processeur. Par exemple, si je prends un processeur 16 bits, il peut adresser en tout 2^16 = 65536 adresses et l'ensemble de ces adresses forme son espace d'adressage. L'espace d'adressage n'est pas la mémoire réellement installée : s'il n'y a pas assez de RAM installée, des adresses seront inoccupées. De plus, une partie de l'espace d'adressage peut être détourné pour communiquer avec les périphériques, comme nous le verrons plus bas. Nous verrons aussi dans ce chapitre qu'il est possible qu'un processeur ait plusieurs espaces d'adressages séparés. Et même si cela peut sembler contre-intuitif, nous allons voir que les architectures avec plusieurs espaces d'adressage sont plus simples à comprendre !
L'adressage de la RAM et de la ROM
modifierAvoir plusieurs espaces d'adressage spécialisés est quelque chose que nous avons déjà rencontré dans les chapitres précédents, mais sans le dire ouvertement. Aussi, nous allons faire quelques rappels succincts sur les cas déjà rencontrés. En premier lieu, nous allons rappeler la différence entre architectures Von Neumann et Hardvard. La différence entre les deux tient dans l'adressage de la mémoire RAM et de la mémoire ROM : est-ce que les deux sont dans un seul espace d'adressage, ou est-ce qu'elles ont chacun leur propre espace d'adressage séparé.
Les architectures Von Neumann
modifierSi on n'a qu'un seul espace d'adressage unique, il est utilisé pour adresser non seulement la mémoire RAM, mais aussi la mémoire ROM. On est alors face à une architecture Von Neumann, où un seul espace d'adressage est découpé entre la mémoire RAM d'un côté et la mémoire ROM de l'autre. Une adresse correspond soit à la mémoire RAM, soit à la mémoire ROM, mais pas aux deux. Typiquement, la mémoire ROM est placée dans les adresses hautes, les plus élevées, alors que la RAM est placée dans les adresses basses en commençant par l'adresse 0. C'est une convention qui n'est pas toujours respectée, aussi mieux vaut éviter de la tenir pour acquise.
Les architectures Harvard
modifierAvec l'architecture Harvard, on a un espace d'adressage séparé pour la RAM et la ROM. Une même adresse peut correspondre soit à la ROM, soit à la RAM : le processeur voit bien deux mémoires séparées, chacune dans son propre espace d'adressage. Les deux espaces d'adressage n'ont pas forcément la même taille : l'un peut contenir plus de mémoire/adresses que l'autre. Il est par exemple possible d'avoir un plus gros espace d'adressage pour la RAM que pour la ROM. Mais cela implique que les adresses des instructions et des données soient de taille différentes. C'est peu pratique et c'est rarement implémenté, ce qui fait que le cas le plus courant est celui où les deux espaces d'adressages ont la même taille.
L'adressage des périphériques
modifierSi l'adressage des mémoires RAM/ROM est important, il faut aussi penser à l'adressage des périphériques. En effet, la communication avec les périphériques se fait par l'intermédiaire de registres d’interfaçage. Et là encore, ces registres peuvent avoir un espace d'adressage séparé, ou être inclus dans l'espace d'adressage des mémoires. Dans ce qui suit, nous allons supposer que l'architecture des de type Von Neumann pour simplifier les explications.
L'espace d'adressage séparé pour les entrées-sorties
modifierLes entrées-sorties et périphériques peuvent avoir leur propre espace d'adressage dédié, séparé de celui utilisé pour les mémoires. Sur ce genre d'architectures, on trouve un espace d'adressage pour la mémoire RAM et la mémoire ROM, et un espace d'adressage spécialisé pour les périphériques et les entrées-sorties.
Une même adresse peut donc adresser soit une entrée-sortie, soit une case mémoire. Et pour faire la différence, le processeur doit avoir des instructions séparées pour adresser les périphériques et la mémoire. Il a des instructions de lecture/écriture pour lire/écrire en mémoire, et d'autres pour lire/écrire les registres d’interfaçage. Sans cela, le processeur ne saurait pas si une adresse est destinée à un périphérique ou à la mémoire. Cela élimine aussi les problèmes avec les caches : les accès à l'espace d'adressage de la RAM passent par l'intermédiaire de la mémoire cache, alors les accès dans l'espace d'adressage des périphériques le contournent totalement.
Là encore, les deux espaces d'adressage n'ont pas forcément la même taille. Il arrive que les deux espaces d'adressage aient la même taille, le plus souvent sur des ordinateurs complexes avec beaucoup de périphériques. Mais les systèmes embarqués ont souvent des espaces d'adressage plus petits pour les périphériques que pour la ou les mémoires. L'implémentation varie grandement suivant le cas, la première méthode imposant d'avoir deux bus séparés pour les mémoires et les périphériques, l'autre permettant un certain partage du bus d'adresse. Nous reviendrons dessus plus en détail dans le chapitre sur l'adressage des périphériques.
Les entrées-sorties mappées en mémoire
modifierSur les ordinateurs avec un seul espace d'adressage, une partie de l'espace d'adressage peut être détourné pour communiquer avec les périphériques. L'idée est que le périphérique se retrouve inclus dans l'ensemble des adresses utilisées pour manipuler la mémoire : on dit qu'il est mappé en mémoire. Les adresses mémoires associées à un périphérique sont redirigées automatiquement vers le périphérique en question. On parle alors d'entrées-sorties mappées en mémoire.
On remarque ainsi le défaut inhérent à cette technique : les adresses utilisées pour les périphériques ne sont plus disponibles pour la mémoire RAM. Dit autrement, on ne peut plus adresser autant de mémoire qu'avant. La perte peut être très légère ou très importante, en fonction des périphériques installés et de leur gourmandise en adresses mémoires. C'est ce qui causait autrefois un problème assez connu sur les ordinateurs 32 bits, qui ne géraient que 2^32 octets = 4 gibioctets. Certaines personnes installaient 4 gigaoctets de mémoire sur leur ordinateur 32 bits et se retrouvaient avec « seulement » 3,5 à 3,8 gigaoctets de mémoire, les périphériques prenant le reste.
Notons qu'il est possible que la RAM d'un périphérique soit mappée en RAM. Un exemple classique est celui des cartes graphiques qui incorporent une mémoire RAM appelée la mémoire vidéo. La mémoire vidéo est mappée en mémoire, ce qui permet au processeur d'écrire directement dedans. Toute lecture ou écriture dans les adresses associées est redirigée vers le bus PCI/AGP/PCI-Express. Nous verrons plus bas des exemples d'ordinateurs où la mémoire vidéo est mappée en mémoire, que ce soit totalement ou partiellement.
Si je dis totalement ou partiellement, c'est parce que les cartes graphiques modernes disposent de tellement de mémoire qu'on ne peut pas la mapper totalement dans l'espace d'adressage. Sur les systèmes 32 et 64 bits, avec un bus PCI-Express d'avant 2008, seuls 256 mégaoctets de mémoire vidéo sont mappés en mémoire RAM. Le reste de la mémoire vidéo est invisible du point de vue du processeur, mais manipulable par le GPU à sa guise. Après 2008, la spécification du PCI-Express ajouta un support de la technologie Resizable Bar, qui permet au processeur d’accéder directement à plus de 256 mégaoctets de mémoire vidéo, voire à la totalité de la mémoire vidéo.
La memory map d'un ordinateur
modifierLes deux sections précédentes nous ont appris que l'on peut utiliser un espace d'adressage séparé pour la ROM et un autre pour les périphériques. En tout, cela donne quatre possibilités distinctes.
IO mappées en mémoire | IO séparées | |
---|---|---|
ROM mappée en mémoire (architecture Von Neumann) | Un seul espace d'adressage | Deux espaces d'adressage :
|
ROM séparée (architecture Harvard) | Deux espaces d'adressage :
|
Trois espaces d'adressages :
|
Les quatre solutions ont des avantages et inconvénients divers, mais il est intéressant de contraster un espace d'adressage unique avec plusieurs espaces d'adressages. Avec un seul espace d'adressage, des adresses censées être disponibles pour la RAM sont détournées vers la ROM ou les périphériques. Et cela limite la quantité de RAM qui peut être réellement adressée en pratique.
Mais c'est un défaut qui se manifeste seulement pour les petits espaces d'adressages, de 8 à 16 bits, pour lesquels on ne peut pas adresser beaucoup de RAM. Par exemple, avec des adresses codées sur 16 bits, utiliser un espace d'adressage unique serait compliqué. On est déjà limité à 64 kibioctets de RAM, si on rajoute une ROM et beaucoup d'entrées-sorties, la quantité de RAM chute rapidement. Par contre, pour des adresses de 32 à 64 bits, l'usage d'un espace d'adressage unique est clairement la solution la plus simple. Une bonne partie de l'espace d'adressage est inutilisé, car il n'y a pas assez de RAM. Détourner ces adresses inutilisées pour mapper une ROM ou des entrées-sorties permet de mieux utiliser l'espace d'adressage.
Avec un espace d'adressage unique, les adresses hautes sont réservées aux périphériques et aux mémoires ROM, alors que les adresses basses sont pour la RAM. La ROM est au sommet de l'espace d'adressage, les périphériques sont juste en-dessous, la RAM commence à l'adresse 0 et prend les adresses basses. Faire simplifie grandement l'implémentation matérielle de l'adressage.
Notons que d'autres composants que les périphériques ou les mémoires peuvent se trouver dans l'espace d'adressage. On peut y trouver les horloges temps réels, des timers, des senseurs de température, ou d'autres composants placés sur la carte mère. Un exemple un peu original est le suivant : la console de jeu Nintendo DS incorporait une unité de calcul spécialisée dans les divisions et racines carrées, séparée du processeur, qui était justement mappée en mémoire !
Les premiers micro-ordinateurs et consoles de jeux
modifierLes vielles machines, notamment les premiers ordinateurs comme les Commodores et les Amiga et les vielles consoles de jeux, utilisaient un espace d'adressage unique. Elles n'avaient pas une variété de cartes graphiques ou de cartes sons différentes, comme sur les PCs modernes. Au contraire, elles avaient la même configuration matérielle, le matériel ne pouvait pas être changé ni upgradé. De plus, de telles machines n'avaient pas de système d'exploitation, ou bien celui-ci était rudimentaire et ne contrôlait pas vraiment l'accès au matériel. Les programmeurs avaient donc totalement accès au matériel et mapper les entrées/sorties en mémoire rendait la programmation des périphériques très simple.
-
Adressage mémoire (carte mémoire) du N5200mk2.
-
Adressage mémoire (carte mémoire) du PC-9801VM.
Les PC IBM x86
modifierUn autre exemple est celui des ordinateurs PC un peu anciens, avec des processeurs x86. L'organisation de leur espace d'adressage a évolué dans le temps, et l'espace d'adressage s'est adapté. Mais il s'est adapté sans modifier l'existant, pour des raisons de compatibilité. Au tout début, les processeurs x86 avaient des adresses de 20 bits, ce qui fait 1 mébioctet de mémoire adressable. La mémoire adressable était alors peuplée par de la RAM, une ROM pour le BIOS, et des périphériques standardisés comme des cartes vidéos VGA/EGA. La RAM prenait les adresses basses, la ROM était au sommet de l'espace d'adressage, et les périphériques entre les deux.
Mais par la suite, l'espace d'adressage s'est agrandit, pour passer de 20 bits à 24 bits, puis à 32 bits. L'espace d'adressage ayant grandit, les adresses au-delà du premier mébioctet ont été allouées à de la RAM. La ROM et les périphériques sont restés à leur place, dans le premier mébioctet. La mémoire au-delà du premier mébioctet est appelée la mémoire étendue. Elle est apparue quand les processeurs x86 32 bits sont apparus. La mémoire étendue n'est pas réservée pour une utilisation précise, les programmes et l'SO peuvent en faire ce qu'ils veulent.
Le premier mébioctet de mémoire est décomposé en deux portions de mémoire : les premiers 640 kibioctets sont ce qu'on appelle la mémoire conventionnelle, les octets restants forment la mémoire haute. La mémoire conventionnelle est réservée à la RAM. Elle est segmentée comme suit par le BIOS :
- Les deux premiers kibioctets de la mémoire conventionnelle sont initialisés au démarrage de l'ordinateur. Ils sont utilisés pour stocker le vecteur d'interruption (on expliquera cela dans quelques chapitres) et servent aussi au BIOS. La portion réservée au BIOS, la BIOS Data Area, mémorise des informations en RAM. Elle commence à l'adresse 0040:0000h, a une taille de 255 octets, et est initialisée lors du démarrage de l'ordinateur.
- Le reste de la mémoire conventionnelle est réservée au le système d'exploitation (MS-DOS, avant sa version 5.0) et au programme en cours d’exécution.
La mémoire haute est réservée aux ROM et aux péripériques, BIOS inclu :
- Le bas de la mémoire haute est réservé pour communiquer avec les périphériques. On y trouve les BIOS des périphériques (dont celui de la carte vidéo, s'il existe) , qui sont nécessaires pour les initialiser et parfois pour communiquer avec eux. De plus, on y trouve la mémoire de la carte vidéo, et éventuellement la mémoire d'autres périphériques comme la carte son.
- Le sommet de la mémoire haute est réservé au BIOS.
La memory map d'un processeur 64 bits
modifierSur les systèmes 64 bits, l'espace d'adressage est énorme : plusieurs millions de tera-octets. Mais le bus d'adresse ne fait pas 64 bits, afin d'économiser des interconnexions, de simplifier le bus d'adresse. En réalité, il fait 48 bits dans le cas général, même si quelques processeurs utilisent 57 bits. Prenons le cas avec 48 bits, le plus courant actuellement. Il manque donc 64 - 48 = 16 bits d'adresses, qui ne peuvent pas être utilisés pour adresser quoi que ce soit. Le fait de n'utiliser que des adresses réelles de 48 bits a des conséquences assez importantes.
Avec ce système, seules les 48 bits de poids faible codent une adresse, les autres bits sont gérés autrement. Sur les architectures 64 bits, la règle est que ces 16 bits doivent être tous égaux : soit ils valent tous 0, soient ils sont tous à 1. Impossible d'avoir un 0000 0100 1100 1100 dans les 16 bits de poids fort, seules les valeurs 1111 1111 1111 1111 et 0000 0000 0000 0000 sont autorisées. Les adresses qui respectent cette contrainte sont appelées des adresses canoniques. Le résultat est que l'espace d'adressage est coupé en trois sections, comme illustré ci-dessous.
- Les adresses canoniques basses ont leurs 16 bits de poids fort à 0 et sont situées en bas de l'espace d'adressage, dans les premières adresses.
- Les adresses canoniques hautes ont leurs 16 bits de poids fort à 1 et sont situées au sommet de l'espace d'adressage, dans les dernières adresses.
- Entre les deux, se trouvent des adresses non-canoniques, qui ne sont pas accessibles. Y accéder déclenche la levée d'une exception matérielle.
- Les futurs systèmes x86 devraient passer à des adresses de 57 bits, ce qui conservera la séparation en trois sections mais avec des frontières différentes.
Les adresses non-canoniques sont censées être inutilisables. Mais les programmeurs aimeraient bien pouvoir les utiliser pour des pointeurs tagués, à savoir des pointeurs/adresses associées à des informations. L'idée serait d'utiliser les 16 bits de poids fort pour stocker des informations liées au pointeur, seuls les 48 bits restant codant l'adresse. Les 16 bits peuvent être utilisés de manières très diverses.
Un exemple est la technique du memory tagging, qui consiste à créer une somme de contrôle au pointeur. La somme de contrôle est générée par un algorithme cryptographique, à partir de l'adresse du pointeur, et elle est vérifiée à chaque utilisation du pointeur. Si la somme de contrôle ne correspond pas au pointeur, alors une erreur est levée. L'intérêt est une question de sécurité. Si jamais un virus ou un code malveillant modifie un pointeur, il ne saura pas comment calculer la somme de contrôle. En cas de modification du pointeur, la somme de contrôle a énormément de chances d'être incorrecte.
Quelques fonctionnalités des processeurs visent à autoriser l'utilisation des adresses non-canoniques. L'idée est que les 16 bits de poids fort sont ignorées lors des accès mémoire, ce qui permet d'utiliser les 16 bits de poids fort à volonté. Sur ARM, il s'agit de la technique du TBI : Top Byte Ignore. Chez Intel et AMD, il s'agit des fonctionnalités UAI (Upper Address Ignore) d'AMD et de LAM (Linear Address Masking) d'Intel.
La commutation de banques (bank switching)
modifierLe bank switching, aussi appelé commutation de banque, permet d'utiliser plusieurs espaces d'adressage sur un même processeur, sans attribuer chaque espace d'adressage pour une raison précise. L'espace d'adressage est présent en plusieurs exemplaires appelés des banques. Les banques sont numérotées, chaque numéro de banque permettant de l'identifier et de le sélectionner.
Le but de cette technique est d'augmenter la mémoire disponible pour l'ordinateur. Par exemple, supposons que j'ai besoin d'adresser une mémoire ROM de 4 kibioctets, une RAM de 8 kibioctets, et divers périphériques. Le processeur a un bus d'adresse de 12 bits, ce qui limite l'espace d'adressage à 4 kibioctets. Dans ce cas, je peux réserver 4 banques : une pour la ROM, une pour les périphériques, et deux banques qui contiennent chacune la moitié de la RAM. La simplicité et l'efficacité de cette technique font qu'elle est beaucoup utilisée dans l'informatique embarquée.
Cette technique demande d'utiliser un bus d'adresse plus grand que les adresses du processeur. L'adresse réelle se calcule en concaténant le numéro de banque avec l'adresse accédée. Le numéro de la banque actuellement en cours d'utilisation est mémorisé dans un registre appelé le registre de banque. On peut changer de banque en changeant le contenu de ce registre. Le processeur dispose souvent d'instructions spécialisées qui en sont capables.