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 !

Les processeurs avec un seul espace d'adressage

modifier

Pour le moment, considérons le cas intuitif où on ne dispose que d'un seul espace d'adressage. Même si on omet les portions inoccupées de l'espace d'adressage, la RAM n'est pas la seule occupante de l'espace d'adressage. On y trouve aussi la mémoire ROM, les périphériques et d'autres choses encore.

Les architectures Von Neumann

modifier

Si 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.

 
Vision de la mémoire par un processeur sur une architecture Von Neumann.

Les entrées-sorties mappées en mémoire

modifier

Sur 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.

 
IO 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. Et mine de rien, quand on a une carte graphique avec 512 mégaoctets de mémoire intégrée, une carte son, une carte réseau PCI, des ports USB, un port parallèle, un port série, des bus PCI Express ou AGP, et un BIOS à stocker dans une EEPROM/Flash, ça part assez vite.

L'exemple des cartes graphiques modernes

modifier

Notons qu'il est possible que la RAM d'un périphérique soit mappée en RAM. Et pire : il arrive que seule une partie le soit. Un exemple classique est celui des cartes graphiques. Seule une portion de la mémoire vidéo (celle de la carte 3D) est mappée en mémoire RAM. Le processeur a donc accès à une partie de la mémoire vidéo, dans laquelle il peut lire ou écrire comme bon lui semble. Le reste de la mémoire vidéo est invisible du point de vue du processeur, mais manipulable par le GPU à sa guise.

Il est possible pour le CPU de copier des données dans la portion invisible de la mémoire vidéo, mais cela se fait de manière indirecte en passant par le GPU d'abord. Il faut typiquement envoyer une commande spéciale au GPU, pour lui dire de charger une texture en mémoire vidéo, par exemple. Le GPU effectue alors une copie de la mémoire système vers la mémoire vidéo, en utilisant un contrôleur DMA intégré au GPU. Pour résumer, tout se passe comme si la mémoire partagée entre CPU et GPU était coupée en deux : une portion sur le GPU et une autre dans la RAM système.

 
Interaction du GPU avec la mémoire vidéo et la RAM système sur une carte graphique dédiée

Pour un périphérique PCI-Express, la portion de mémoire vidéo visible est configurée via des registres spécialisés, appelés les Base Address Registers (BARs). La configuration des registres précise quelle portion de mémoire vidéo est adressable par le processeur, quelle est sa taille, sa position en mémoire vidéo, etc. Avant 2008, les BAR permettaient d’accéder à seulement 256 mégaoctets, pas plus. 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. De nombreux fabricants de cartes graphiques commencent à incorporer cette technologie, qui demande quelques changements au niveau du système d'exploitation, des pilotes de périphériques et du matériel.

La memory map d'un ordinateur avec un seul espace d'adressage

modifier

Outre la mémoire RAM principale, des mémoires vidéo et même plusieurs mémoires ROM sont mappées en mémoire. Il y a un unique espace d'adressage qui contient tout ce qui est adressable : toutes les mémoires et tous les périphériques de l'ordinateur. Généralement, 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.

 
Espace d'adressage classique avec entrées-sorties mappées en mémoire

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

modifier

Les vielles machines, notamment les premiers ordinateurs comme les Commodores et les Amiga et les vielles consoles de jeux, utilisaient cette méthode pour sa simplicité. Ces machines n'étaient pas comme les ordinateurs personnels, pour lesquels on a une variété de cartes graphiques ou de cartes sons différentes. Tous avaient la même configuration matérielle, le matériel était fourni tel quel, ne pouvait pas être changé ni upgradé. Toutes les commodores 64 avaient exactement le même matériel, par exemple : la même carte son, la même carte graphique, les mêmes périphériques.

Cette standardisation faisait que cela ne servait à rien de limiter l'accès au matériel. 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.

Les PC IBM x86

modifier

Un autre exemple est celui des ordinateurs PC un peu anciens, avec des processeurs x86. A l'époque, les processeurs x86 avaient des adresses de 20 bits, ce qui fait 1 mébioctet de mémoire adressable. 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, alors que les octets restants forment la mémoire haute. La mémoire au-delà du premier mébioctet, la mémoire étendue, est apparue quand les processeurs x86 32 bits sont apparus.

  • 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 à la mémoire RAM utilisée par le système d'exploitation (MS-DOS, avant sa version 5.0) et le programme en cours d’exécution.
  • 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 mémoire étendue n'est pas réservée pour une utilisation précise.
 
Organisation Mémoire des vieux PC, à l'époque du DOS.

Les processeurs avec plusieurs espaces d'adressages

modifier

Il existe des processeurs qui sont capables de gérer plusieurs espaces d'adressage. Cela peut paraitre surprenant, mais nous avons déjà abordé un exemple dans les chapitres précédents (essayez de deviner lequel). Toujours est-il que l'on peut se demander quelle est l'utilité d'avoir plusieurs espaces d'adressage. La raison est pourtant simple, et même intuitive. Avec un seul espace d'adressage, les périphériques et la ROM sont mappés dans l'espace d'adressage. Des adresses censées être disponibles pour la RAM sont détournées vers la ROM ou les périphériques. Si très peu de RAM est installé, alors ce n'est pas un problème : des adresses inutilisées sont détournées pour des choses utiles. Mais si on veut utiliser plus de RAM, les choses se compliquent. L'idée est d'utiliser plusieurs espaces d'adressage dans lesquels on ne met pas la même chose, d'utiliser des espaces séparés pour des utilisations distinctes. On peut par exemple utiliser un espace d'adressage séparé pour la RAM, un autre pour la ROM, un autre pour les périphériques, etc. En dire plus demande de détailler plusieurs techniques qui utilisent chacune un espace d'adressage séparé.

Les architectures Harvard

modifier

Le premier cas d'espace d'adressage séparé est celui des architectures Harvard. Pour rappel, avec 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.

 
Vision de la mémoire par un processeur sur une architecture Harvard.

L'espace d'adressage séparé pour les entrées-sorties

modifier

Les entrées-sorties et périphériques peuvent avoir leur propre espace d'adressage dédié, séparé de celui utilisé pour la mémoire. 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.

 
Bit IO.

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 gérer les périphériques et adresser 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.

La commutation de banques (bank switching)

modifier

Le 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.

 
exemple de Bank switching.

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.