wiki:TME2-2014

Version 3 (modified by franck, 14 years ago) (diff)

--

Le code en RAM et première interruption

Objectif

L'objectif général de ce second TME est également de faire que chaque processeur affiche un message "Hello", mais après que le code ait été préalablement déplacé de la rom vers la ram. Nous allons également gérer la première interruption. Les étapes:

  1. Nous allons modifier le programme de boot pour qu'il recopie dans la ram le code des fonctions __do_init() et tty_puts() avant de d'y sauter pour les exécuter.
  2. Nous allons ajouter l'affichage du timestamp counter de chaque processeur devant le message "hello" en utilisant une fonction tty_putx() qui affiche un nombre en hexadécimale.
  3. Nous allons refaire l'étape 1 en faisant faire la copie du code par le module DMA. Vous noterez la différence de vitesse grâce à l'affichage du timestamp.

1. Hello en ram

Le programme exécuté jusque là s'exécutait directement dans la ROM. Cette mémoire n'est pas cachée par les cache L1. Elle n'est donc pas très rapide.

  • Nous allons placer le code des fonctions C __do_init(), tty_puts(), tty_putx, ... dans une autre section de la mémoire. Ces fonctions seront compilées dans le but d'une exécution dans la section ktext, mais on demandera à l'éditeur de lien de les placer dans la section ktext_lma_base de la ROM.
  • Nous allons ensuite modifier le code du programme de boot pour que l'un des processeurs se charge du déplacement des programmes depuis la ROM jusque dans la mémoire RAM. Une fois que le programme est recopié, tous les processeurs saute à leur fonction __do_init().

2. Hello en chiffre

Pour déterminer la durée d'exécution de certaines opération, le MIPS propose un registre dans son coprocesseur 0 qui s'incrémente à cycle d'horloge.

  • Nous allons écrire une fonction unsigned getTimeStamp() permettant de récupérer la valeur de ce registre en y plaçant le code assembleur nécessaire. Cette fonction sera inlinée.
  • Nous allons enuite écrire une fonction `tty_putx(unsigned int tty, unsigned i)}}} qui écrit sur le terminal tty, la chaine de caractère représentant le valeur du nombre i en hexadécimal.
  • La fonction __do_init() devra écrire le message "Hello at " suivi du nombre de cycle rendu par getTimeStamp()

3. Hello avec le dma

Le déplacement en ram est une nécessité pour bénéficier des caches, mais la copie est lente si c'est le processeur qui s'en charge. Or il existe un composant spécialement adapté aux transfert de données, c'est le DMA.

  • Nous allons modifier le programme de boot pour que la boucle de copie soit remplacée par une programmation d'une requête DMA. La terminaison de la requête DMA produit normalement une interruption. Nous n'allons pas pouvoir l'utiliser ici car le gestionnaire d'interruption n'est pas encore en place. nous allons donc tester le registre LEN du DMA afin de savoir si le transfert est terminé. Le bus système transfert en moyenne 2 octets par cycles, il est donc possible d'évaluer approximativement la fin de l'opération.
  • Vous exécutez les codes __do_init() en notant la différence de date.

4. Première interruption

Il s'agit maintenant de commencer à traiter les interruptions. Nous allons seulement traiter les interruptions venant des TTY. Nous allons pour cela mettre un bout de code à l'adresse du point d'entrée du système (pour le mips32 c'est 0x80000180). Ce code va devoir analyser le registre de cause qui contient la raison pour laquelle le système est invoqué. Nous n'allons considérer que deux causes. Soit c'est une interruption, soit c'est autre chose. Dans le cas d'une interruption, nous sauvegarderons dans la pile courante, les registres temporaires avant d'appeler la fonction __do_interrupt(). Au retour de la fonction, les registres sont restaurés et on retourne au code interrompu. La fonction __do_interrupt() prendra comme paramètre, le numéro du CPU et le masque des interruptions (le second octet du registre cause). Son but est de déterminer quelle TTY a émis l'interruption, lire le caractère (ce qui acquitte l'interruption) et l'écrire sur l'écran. C'est un echo. Il faudra aussi modifier do_init pour initialiser l'ICU.

Attachments (3)

Download all attachments as: .zip