* * *
PMMU2, le Retour
* * *


 Après avoir vu les registres et le fonctionnement global de la PMMU, il ne nous reste plus qu'à voir les instructions et une petite utilisation de la PMMU : le mapping de fichier en mémoire virtuelle. Mais avant tout, il y a une chose dont je n'ai pas parlé : le cache de la table de traduction.

Le cache de traduction d'adresse : l'ATC


 Ce cache permet de faire la correspondance entre une adresse logique et une adresse physique. Il est composé de 22 entrées, dont chacune est décomposé comme suit :

     Partie "logique" de l'entrée    Partie "Physique" de l'entrée
              2         1                       2         1
     7 654 321098765432109876543210  7 6 5 4 321098765432109876543210
     - --- ------------------------  - - - - ------------------------
     ^ ^   ^                         ^ ^ ^ ^ ^
     V FC  adresse logique           B C W M adresse physique
                                       I P


 La signification des bits est la suivante : - V : indique la validité de cette entrée

 Je ne vais pas vous expliquer comment marche un cache, mais le principe est le suivant : on stocke dans cette petite mémoire (22 entrées seulement!) rapide les correspondances page logique->page physique. Ensuite au lieu de parcourir toutes les tables de traduction, on commence par regarder si par hasard on aurait pas la correspondance pour la page logique que l'on cherche. On comprend vite l'intérêt de ce cache, car à chaque accès mémoire, il y a un besoin de traduction (même pour lire le code!), donc chaque accès mémoire se traduirait par 3 ou 4 accès supplémentaires! On arrive donc à une machine 3 ou 4 fois plus lente! Heureusement le cache fonctionne bien, et donc souvent, la correspondance page logique->page physique est présente.
 Mais pourquoi je vous parle du cache? Et bien parcequ'il peut poser un problème. Imaginez que pour une raison ou une autre, une page logique doit changer de place en mémoire physique. Pour ce faire, vous copier votre page à la nouvelle place, modifiez votre table de traduction, et le tour est joué! Sauf, si par (malchance??) hasard la correspondance page logique->page physique se trouve dans le cache, et donc lors du prochain accès à cette page, vous allez obtenir l'ancienne place de cette page! Ce problème se fait plus ressentir dans des commutations de processus lourd, ou il faut changer presque toutes les correspondances page logique->page physique.


Les instructions de la PMMU

 La PMMU est un coprocesseur, et donc utilise les instructions cp????. Mais au lieu de devoir préciser le numéro du coprocesseur (%000, pour la PMMU), on utilise les instructions en P???? qui s'adresse directement à la PMMU. La liste des instructions est la suivante :

PBcc                Saut sur condition de la PMMU

     PBcc.<taille du deplacement> <adresse de saut>

     permet  de faire un saut suivant les conditions de la MMU (le  registre 
     MMUSR). Les conditions sont les suivantes : 

          BS : B à 1               BC : B à 0
          LS : L à 1               LC : L à 0
          SS : S à 1               SC : S à 0
          AS : A à 1               AC : A à 0
          WS : W à 1               WC : W à 0
          IS : I à 1               IC : I à 0
          GS : G à 1               GC : G à 0
          CS : C à 1               CC : C à 0

PDBcc               Tester, décrémenter, et saut

     PDBcc Dn, <adresse de saut>

     test une condition,  si elle fausse,  il y a décrémentation du registre 
     de donnée Dn,  et saut à l'adresse de saut si ce dernier est  différent 
     de -1. Les codes conditions sont les mêmes que pour PBcc.

PFLUSH              Invalide une entrée de l'ATC

     PFLUSHA
     PFLUSH Fc, masque
     PFLUSH Fc, masque, <adresse effective>

     Cette  instruction  permet d'invalider (elles ne seront  plus  utilisée 
     pour  la  traduction) des entrées dans le cache  de  la  PMMU.  PFLUSHA 
     invalide  toutes  les  entrées  du  cache.  PFLUSH  Fc,  masque  permet 
     d'invalider des entrées qui ont les bits FC correspondant.  La dernière 
     forme permet d'invalider une entrée spécifique à une adresse.

PLOAD               Charge une entrée dans le cache

     PLOADR Fc,<ea>
     PLOADW Fc,<ea>

     Cette  instruction charge une entrée de l'ATC avec  une  correspondance 
     adresse  logique (l'adresse effective) -> adresse physique  en  prenant 
     soin  de respecter les bits FC.  Il existe deux variantes  :  une  pour 
     l'écriture (PLOADW), et une autre pour la lecture (PLOADR).


PMOVE               Accès aux registres de configuration de la PMMU

     PMOVE MRn,<adresse effective>
     PMOVE <adresse effective>,MRn
     PMOVEFD <adresse effective>,MRn

     Cette   instruction   permet   de  lire/modifier   les   registres   de 
     configuration de la PMMU. Les transferts se font entre la mémoire et un 
     registre de la PMMU.  PMOVEFD permet d'invalider le cache de traduction 
     d'adresse,  en  même temps que l'instruction.  Ceci est  très  pratique 
     lorsque la configuration mémoire est très boulversée.

PTEST               Test une adresse logique

     PTESTR Fc,<adresse effective>,#<niveau max>
     PTESTR Fc,<adresse effective>,#<niveau max>,An
     PTESTW Fc,<adresse effective>,#<niveau max>
     PTESTW Fc,<adresse effective>,#<niveau max>,An

     Cette  instruction cherche dans les tables de traduction la  traduction 
     de  l'adresse  logique.  Les  registres MMUSR  contient  l'état  lié  à 
     l'adresse  logique.  Ainsi si une adresse logique provoque  une  erreur 
     bus,  le bit B à 1. Fc, représente l'état des bits de fonctions lors de 
     la recherche de la traduction de l'adresse effective. Niveau max permet 
     de  borner le nombre de niveau de table de traduction dans lesquels  la 
     recherche s'effectue.  Si niveau max=0, seul le cache est testé. Il est 
     possible  de  stocker,   dans  un  registre  d'adresse,   l'adresse  du 
     descripteur de page de la page logique.  PTESTR test la  correspondance 
     adresse  logique->adresse physique pour une lecture et PTESTW pour  une 
     écriture.

 Voilà l'ensemble des instructions lié à la PMMU. Maintenant voici le premier exemple d'utilisation de la PMMU :



Le mapping de fichier en mémoire



 Le mapping de fichier en mémoire consiste à faire croire au programme qu'un fichier est en mémoire alors qu'il ne l'est pas. Il est ainsi possible de manipuler un fichier de plusieurs dizaine de Mo sur un Falcon avec 4 Mo de mémoire. Le principe est le suivant : charger les parties utilisées du fichier en mémoire et les placer dans la mémoire virtuelle. Il faut savoir maintenant quels sont les parties chargées en mémoire et celles qui ne le sont pas, et ou. Cela se réalise grâce à la table de traduction : lorsque le descripteur de page n'est pas valide c'est que la page n'est pas en mémoire, et donc qu'il va falloir la charger. Lorsque l'on tente d'accéder à une page non valide, il y a une erreur bus. En récupérant cette erreur bus, on peut savoir si elle a eu lieu à cause d'un défaut de traduction (on connaît l'adresse en question, et on peut déterminer si cette dernière appartient au fichier mappé ou pas), et dans ce cas on charge la page correspondante à l'adresse logique désirée.

 Mais pour arriver à ceci, il faut savoir faire plusieurs choses. Savoir quelle page physique sont occupées, et par qui. Pour ceci, il y a aussi des descripteurs de page physique. Ces descripteurs contiennent l'adresse phy-sique de la page qu'ils décrivent, son adresse logique, et l'adresse du descripteur de page correspondant. Notez que ce dernier peut être retrouvé grâce à l'instruction PTEST.

 Pour résumer, le principe est le suivant :

 Pour y arriver, il nous faut reprogrammer la PMMU, changer la table de traduction, détourner les exceptions erreur bus et erreur PMMU (si on est très maladroit, on se sait jamais!).

 La PMMU se trouve configurée de la manière suivante :


 Ce qui nous donne comme mot de configuration : $80C04448 (les amateurs appréciront!). Aucune limite n'est mise sur la taille de la mémoire virtuelle. Il n'y a pas utilisation des registres de transparence. L'initialisation de la PMMU se déroule dans la routine creer_pmmu. Dans cette routine il a création de la configuration PMMU en mémoire, puis chargement de cette configuration. Ensuite on invalide le cache de traduction, pour détruire tous les relicats de traductions incorrectes.

 La table de traduction est basé sur la table de traduction du système. Ainsi les 16 premiers Mo sont directement traduit (adresse logique=adresse physique), ainsi que les 16 derniers (ils correspondent en fait au 16 premiers !). Dans cette exemple, seulement le Mo situé à l'adresse $80000000 pourra contenir le fichier. Donc il y a modification de la table de traduction en conséquence. C'est la routine creer_tables qui se charge de faire la copie (avec translation d'adresse!) de la table du système. Ensuite la routine ajout_tables s'occupe de rajouter la partie de traduction nécessaire pour la zone du fichier. Toutes les pages de cette zone sont non présente en mémoire virtuelle.

 Il ne nous reste plus qu'a modifier la table des vecteurs d'exception. On utilise le registre VBR pour savoir ou elle est stockée. Le registre VBR, pour ceux qu'ils ne le savent pas, est l'adresse de début de la tables des vecteurs d'exceptions. On copie cette table, et on modifie cette copie. Ensuite on modifie le registre VBR pour que le 68030 utilise cette table. La routine creer_vecteurs se charge de cette opération.

 Il ne reste plus qu'a initialiser les descripteurs de pages physiques. Chaque descripteur de page physique contient l'adresse du descripteur de page virtuelle qui utilise la page physique; l'adresse physique de la page physique; l'adresse logique de la page. De plus, il y a aussi l'adresse du descripteur de page suivant. Ceci permet de chaîner de manière circulaire (le suivant du dernier est le premier) les descripteurs de page. Ce chaînage sert lors de la recherche de page physique libre. L'algorithme de remplacement de page est le suivant : on remplace la page courante, et on passe à la page suivante. Ainsi on remplace les pages qui sont restée le plus longtemps en mémoire. Ce n'est pas un algorithme optimal, mais il est très simple à implémenter.

 Il ne reste plus qu'a voir le coeur de cet exemple : l'exception erreur bus. La première chose réalisée est de récupérer l'adresse fautive sur la pile. Ensuite on regarde si cette adresse appartient à la zone de mémoire virtuelle. Si elle n'appartient pas à cette zone, alors il y a affichage d'un petit message, restauration de la PMMU, de la table des vecteurs, et retour au système qui va afficher fièrement 2 bombes. Si il s'agit d'une adresse dans la zone virtuelle, alors le traitement est un peu plus long.

 Il faut commencer par trouver une page physique libre. Pour ceci on prend la page physique courante (pointeur desc_courant), on regarde si elle est utilisée par une page logique (adresse de descripteur de page logique différent de 0). Si oui, on modifie le descripteur de page logique (page non valide), et on invalide dans la cache la traduction adresse logique -> adresse physique. On pense desc_courant à la page suivante.


 Il faut ensuite déterminer la page logique fautive. Ceci se réalise en examinant l'adresse logique. On prend les 20 bits de poids faible qui nous donne l'offset de l'octet fautif. Il suffit de diviser par la taille de la page pour obtenir le numéro de page. Ce numéro de page va nous servir à savoir quelle page du fichier mappé il faut charger. Ensuite on place le pointeur sur le fichier au bon endroit, et on lit la taille d'une page.

 Pour modifier la table de traduction, c'est très simple. Sachant l'adresse virtuelle, on utilise ptest qui nous donne l'adresse du descripteur de page, on modifie ce descripteur, ainsi que le descripteur de page physique contenant cette page logique.

 Et voilà la fin de ce premier exemple sur l'utilisation de la mémoire virtuelle. Pour se convaincre de l'intérêt de cette technique il n'y a cas jeter un coup d'oeuil à la routine d'affichage de l'image. On utilise que 16 Ko de mémoire pour charger l'image. C'est un peu du direct to disk, mais en plus simple pour le programmeur! Pour la prochaine fois, on regarde le swap de mémoire. Pour ceux qui ne pourront pas attendre le prochain numéro, une petite astuce : lors de la libération de la page physique, il suffit de regarder si elle a été modifiée, si oui, alors on la sauve sur disque.

  Bon code !





Golio Junior