Changes between Version 23 and Version 24 of Archi-1-TP11


Ignore:
Timestamp:
Dec 11, 2021, 10:28:09 AM (3 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TP11

    v23 v24  
    2020**
    2121{{{#!html
    22 <h1> <font size="+2"> Gestionnaire d'interruptions et application multi-tâches en temps partagé
    23 }}}
    24 Cette page décrit la séance complète : partie TD et partie TP. Elle commence par la partie TD avec des questions ou des exercices à faire sur papier, réparties dans 4 sections. Certaines questions de sections différentes sont semblables, c'est normal, cela vous permet de réviser. Puis, dans la partie TP, il y a des questions sur le code avec quelques exercices de codage simples à écrire et à tester sur le prototype. La partie TP est découpée en 3 étapes. Pour chaque étape, nous donnons (1) une brève description avec une liste des objectifs principaux de l'étape, (2) une liste des fichiers avec un bref commentaire sur chaque fichier, (3) une liste de questions simples dont les réponses sont dans le code, le cours ou le TD et enfin (4) un petit exercice de codage.
     22<h1> <font size="+2"> Gestionnaire d'interruptions
     23}}}
    2524
    2625**IMPORTANT\\Avant de faire cette séance, vous devez avoir lu les documents suivants** :
    2726* [htdocs:cours/AS5-11-4p.pdf Cours sur le gestionnaire d'interruption et les threads] : ''obligatoire''
    2827* [htdocs:cours/doc_MIPS32.pdf Document sur l'assembleur du MIPS et la convention d'appel des fonctions] : ''recommandé, mais déjà lu''
    29 * [wiki:Doc-MIPS-Archi-Asm-kernel Documentation sur le mode kernel du MIPS32] : ''obligatoire''
     28* [wiki:Doc-MIPS-Archi-Asm-kernel Documentation sur le mode kernel du MIPS32] : ''fortement recommandé''
    3029
    3130= A. Travaux dirigés
     
    3332== Rappel de cours
    3433
    35 Il est fortement recommandé de lire les transparents, toutefois, nous avons ajouté ci-après quelques rappels utiles pour répondre aux questions du TD.
     34Il est fortement recommandé de lire les transparents, toutefois, mais nous avons mis ci-après quelques rappels utiles pour répondre aux questions du TD.
    3635
    3736Dans cette séance, noua allons manipuler 3 contrôleurs de périphériques: Le TTY que vous connaissez déjà et deux autres, l'ICU et le TIMER. Ces trois contrôleurs s'utilisent grâce à des registres mappés (placés) dans l'espace d'adressage du MIPS. Les registres du TTY sont placés à partir de l'adresse `0xd0200000`, ceux de l'ICU à partir de l'adresse `0xd1200000` et enfin ceux du TIMER à partir de l'adresse `0xd3200000`. L'explication du rôle de ces registres est rappelée en partie dans ce texte et pour le détail, vous devez revoir le cours.
     
    4443Les IRQ sont des signaux d'état qui doivent rester levés/activés tant qu'ils n'ont pas été acquittés par une ISR. Quand une IRQ se lève, la conséquence est que le programme en cours d'exécution sur le processeur recevant l'IRQ est interrompu et qu'il est dérouté vers le noyau pour que ce dernier exécute l'ISR prévue pour l'IRQ. Notez que ce n'est pas le processeur qui est interrompu, c'est bien le programme, car le processeur est seulement dérouté vers le noyau, mais il continue à travailler.
    4544
     45Sur le schéma de la plateforme des TP, on peut voir que ce sont seulement les composants TTY et TIMER qui peuvent lever des IRQ. Les IRQ de ces contrôleurs de périphériques sont envoyés au composant ICU qui va les combiner pour produire un unique signal IRQ pour le processeur.
     46
    4647[[Image(htdocs:img/Archi_TP11.png,nolink,height=250)]]
    4748
    48 Sur le schéma de la plateforme des TP, on peut voir que ce sont seulement les composants TTY et TIMER qui peuvent lever des IRQ. Les IRQ de ces contrôleurs de périphériques sont envoyés au composant ICU qui va les combiner pour produire un unique signal IRQ pour le processeur.
    49 
    5049Une IRQ peut être masquée, c'est-à-dire que le processeur ne va pas interrompre le programme en cours. Le masquage peut être demandé à plusieurs endroits : dans le composant ICU et dans le processeur lui-même. Le masquage est demandé par le noyau, le plus souvent de manière temporaire, quand il doit exécuter un code critique qui ne doit surtout pas être interrompu.
    5150
    5251[[Image(htdocs:img/IRQ_routage.png,nolink,height=200)]]
    5352
    54 Sur le schéma ci-dessus, on voit que l'IRQ du TTY0 entre sur l'entrée n°`10` de l'ICU, c'est un choix matériel qui n'est pas modifiable par logiciel. Son état est donc enregistré dans le bit n°10 du registre `ICU_STATE`. Il y a un `AND` avec le bit `10` du registre `ICU_MASK`. Si le bit `10` du registre `ICU_MASK` est à `0`, alors la sortie du `AND` est `0` et l'IRQ est masquée (donc invisible pour le processeur). Le registre `ICU_HIGHEST` contient toujours le numéro de l'IRQ active la plus prioritaire, comme il n'y en a qu'une dans cet exemple, `ICU_HIGHEST` contient `10`. L'IRQ de l'ICU entre sur l'entrée `0` des 6 IRQs possibles du MIPS et sa valeur s'inscrit dans le registre `HWI0` du registre `C0_CAUSE`. Il y a un `AND` avec le bit `HWI0` du registre `C0_STATUS`. Si le bit `HWI0` du registre `C0_STATUS` est à 0, alors la sortie du `AND` est `0` et l'IRQ est aussi masquée. Enfin, il y a encore un `AND` qui permet de masquer globalement les IRQ avec le bit `0` de `C0_STATUS` (c'est le bit `IE` pour Interrupt Enable) et le `NOT` du bit `1` de `C0_STATUS` (c'est le bit `EXL` EXception Level).
    55 
    56 Quand le signal IRQ vue par le MIPS s'active (passe à 1), c'est que l'IRQ levée par le contrôleur de périphérique doit être prise en charge. Le programme en cours est interrompu et dérouté vers `kentry` à l'adresse `0x80000180` et en même temps `C0_EPC ← PC+4`, `C0_CAUSE.XCODE ← 0`, `C0_STATUS.EXL ← 1`. Notez que le nom officiel de `C0_STATUS` est `C0_SR`, mais dans ce document, on utilise `C0_STATUS` pour plus de clarté.
    57 
     53Sur le schéma ci-dessus, on voit que l'IRQ du TTY0 entre sur l'entrée n°`10` de l'ICU, c'est un choix matériel qui n'est pas modifiable par logiciel. Son état est donc enregistré dans le bit n°10 du registre `ICU_STATE`. Il y a un `AND` avec le bit `10` du registre `ICU_MASK`. Si le bit `10` du registre `ICU_MASK` est à `0`, alors la sortie du `AND` est `0` et l'IRQ est masquée (donc invisible pour le processeur). Le registre `ICU_HIGHEST` contient toujours le numéro de l'IRQ active la plus prioritaire, comme il n'y en a qu'une dans cet exemple, `ICU_HIGHEST` contient `10` (l'IRQ prioritaire, pour cette ICU, est l'IRQ active dont le numéro est le plus petit). L'IRQ de l'ICU entre sur l'entrée `0` des 6 IRQs possibles du MIPS et sa valeur s'inscrit dans le registre `HWI0` du registre `C0_CAUSE`. Il y a un `AND` avec le bit `HWI0` du registre `C0_STATUS`. Si le bit `HWI0` du registre `C0_STATUS` est à 0, alors la sortie du `AND` est `0` et l'IRQ est aussi masquée. Enfin, il y a encore un `AND` qui permet de masquer globalement les IRQ avec le bit `0` de `C0_STATUS` (c'est le bit `IE` pour Interrupt Enable) et le `NOT` du bit `1` de `C0_STATUS` (c'est le bit `EXL` EXception Level).
     54
     55Quand le signal IRQ vue par le MIPS s'active (passe à 1), c'est que l'IRQ levée par le contrôleur de périphérique doit être prise en charge. Le programme en cours d'exécution est interrompu et dérouté vers `kentry` à l'adresse `0x80000180` et __en même temps__ `C0_EPC ← PC+4`, `C0_CAUSE.XCODE ← 0`, `C0_STATUS.EXL ← 1`. Notez que le nom officiel de `C0_STATUS` est `C0_SR`, mais dans ce document, on utilise `C0_STATUS` pour plus de clarté.
     56
     57Dans le schéma ci-après, à gauche c'est le matériel et à droite c'est un extrait de la RAM contenant les structures de données utilisées par le noyau pour la gestion des IRQ.
    5858
    5959[[Image(htdocs:img/IRQ_VECTOR.png,nolink,height=220)]]
    6060
    61 Dans le schéma précédent, à gauche c'est le matériel et à droite c'est un extrait de la RAM contenant les structures de données utilisées par le noyau.
    6261- À gauche, on voit que les IRQ venant des contrôleurs de périphériques sont connectés aux entrées d'IRQ de l'ICU. Il y a 32 entrées possibles. Sur notre plateforme, par exemple l'IRQ du TTY2 est connectée à l'entrée `12` de l'ICU. Ce numéro d'entrée est le numéro qui identifie le contrôleur de périphérique. Notez que le registre `ICU_MASK` est en lecture seul, c'est-à-dire qu'il ne peut pas être écrit directement. Pour modifier le contenu du registre `ICU_MASK`, il faut utiliser deux autres registres de l'`ICU`: `ICU_SET` et `ICU_CLEAR`. `ICU_SET` permet de mettre à `1` les bits de `ICU_MASK`, et `ICU_CLEAR` permet de les mettre à `0`. Pour mettre à `1` le bit `i` du registre `ICU_MASK`, il faut écrire `1` dans le bit `i` du registre `ICU_SET`. Pour mettre à `0` le bit `j` du registre `ICU_MASK`, il faut aussi écrire `1`, mais dans le bit `j` du registre `ICU_CLEAR`.\\\\
    63 - À droite, il y a les deux tableaux que le noyau utilise pour connaitre l'ISR à exécuter pour chaque numéro IRQ. Ce couple de tableaux se nomme **vecteur d'interruption**. Ici, il est composé des tableaux `IRQ_VECTOR_ISR[]` et `IRQ_VECTOR_DEV[]`. Le vecteur d'interruption est indexé par les numéros d'IRQ. Il contient deux informations: (1) Dans la case n°`i` du tableau `IRQ_VECTOR_ISR[]`, on trouve le pointeur sur la fonction ISR à appeler si l'IRQ n°`i` est levée, et (2) dans la case n°`i` du tableau `IRQ_VECTOR_DEV[]`, on trouve le numéro de l'instance du périphérique. Cette dernière information est nécessaire dans le cas des contrôleurs de périphérique multi-instances comme le TTY afin de savoir quel jeu de registres la fonction ISR doit utiliser. En d'autres termes, il y a une fonction ISR unique quelque-soit le numéro du TTY, l'adresse de cette fonction est placée dans les cases `10`, `11`, `12`, et `13` du tableau `IRQ_VECTOR_ISR[]` (si on a 4 TTYs) et dans les cases  `10`, `11`, `12`, et `13` du tableau `IRQ_VECTOR_DEV[]`, on a `0`, `1`, `2` et `3` qui correspondent bien au numéro d'instance des TTYs.
     62- À droite, il y a les deux tableaux que le noyau utilise pour connaitre l'ISR à exécuter pour chaque numéro IRQ. Ce couple de tableaux se nomme **vecteur d'interruption** et comme il y a 32 entrées d'IRQ dans l'ICU, ces tableaux ont 32 cases chacun. Ici, le vecteur d'interruption est composé des tableaux `IRQ_VECTOR_ISR[]` et `IRQ_VECTOR_DEV[]`. Le vecteur d'interruption est indexé par les numéros d'IRQ. Il contient deux informations: (1) Dans la case n°`i` du tableau `IRQ_VECTOR_ISR[]`, on trouve le pointeur sur la fonction ISR à appeler si l'IRQ n°`i` est levée, et (2) dans la case n°`i` du tableau `IRQ_VECTOR_DEV[]`, on trouve le numéro de l'instance du périphérique. Cette dernière information est nécessaire dans le cas des contrôleurs de périphérique multi-instances comme le TTY afin de savoir quel jeu de registres la fonction ISR doit utiliser. En effet, il y a une fonction ISR unique à exécuter quelque-soit le numéro du TTY, l'adresse de cette fonction est placée dans les cases `10`, `11`, `12`, et `13` du tableau `IRQ_VECTOR_ISR[]` (si on a 4 TTYs) et dans les cases  `10`, `11`, `12`, et `13` du tableau `IRQ_VECTOR_DEV[]`, on a les valeurs `0`, `1`, `2` et `3` qui correspondent bien au numéro d'instance des TTYs.
     63
     64Enfin, nous vous rappelons les 3 registres du coprocesseur système (`c0`) qui sont utilisés au moment de l'entrée dans le noyau, quelque soit la cause : syscall (vu la semaine dernière), interruption (TD de cette semaine) et exception (dans le cas de problèmes lors de l'exécution du programme comme la division par 0). On rappelle aussi que les seules instructions qui peuvent manipuler ces registres sont `mtc0` et `mfc0` pour, respectivement, les écrire et les lire.
    6465
    6566[[Image(htdocs:img/C0_registers.png,nolink,height=300)]]
    66 
    67 Sur le schéma précédent, nous vous rappelons les 3 registres du coprocesseur système qui sont utilisés au moment de l'entrée dans le noyau, quelque soit la cause : syscall (vu la semaine dernière), interruption (TD de cette semaine) et exception (dans le cas de problèmes lors de l'exécution du programme comme la division par 0). On voit aussi que les seules instructions qui peuvent manipuler ces registres sont `mtc0` et `mfc0` pour, respectivement, les écrire et les lire.
    6867
    6968Les bits `HWI0` des registres `C0_STATUS` (aussi nommé `c0_sr`) et `C0_CAUSE` contiennent respectivement le mask et le l'état de l'entrée n°`0` d'interruption du MIPS. Les bits `UM`, `IE` et `EXL` sont liés au mode d'exécution du MIPS: `UM` est le bit de mode du MIPS (`1`=`User Mode`, `0`=`Kernel Mode`), `IE` est le bit de masque général des interruptions (`1`=autorisées, `0`=masquées) et enfin  `EXL` est le bit que le MIPS met à `1` à l'entrée dans le noyau pour informer d'un niveau exceptionnel et dans ce cas les bits `UM` et `IE` ne sont plus significatifs, si `EXL` est à `1` alors le MIPS est en mode kernel, interruptions masquées.