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


Ignore:
Timestamp:
Nov 8, 2023, 6:19:46 PM (19 months ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TD10

    v23 v24  
    2626 [[Image(htdocs:img/os_bigpicture.png,nolink,height=400)]]
    2727
    28 - En bas à gauche, c'est le code de boot qui, ici, se contente d'initialiser la pile d'exécution du noyau et d'entrer dans le noyau par la fonction `kinit()` (kernel init).  Ce code s'exécute en mode `kernel`, mais il ne fait pas partie du noyau car dans un vrai système, il devrait charger le noyau depuis le disque, mais, ici, le noyau est déjà en mémoire.
    29 - En bas, c'est le noyau avec la fonction `kinit()` qui initialise les structures de données internes du noyau, ici, il s'agit juste de mettre les variables globales non initialisées à 0, puis d'appeler la routine `app_load` qui va entrer dans la première fonction de l'application nommée `_start()`. Dans le noyau, on voit aussi, la routine `kentry` qui est le point d'entrée du noyau pour la gestion des services, ici, il n'y a que le gestionnaire d'appel système (`syscall`). Son comportement est succinctement résumé.
    30 - En haut, c'est l'application, décomposée en trois parties. La première à gauche est la fonction `_start()` appelée par le noyau au début de l'application. Cette fonction initialise les variables globales, puis appelle la fonction `main()`. Si on sort de la fonction `main()`, elle fait l'appel système `exit()`. La seconde partie au centre contient le code de l'utilisateur  ''(notez que la fonction `main()` ou l'une des fonctions appelées par la fonction `main()` peut demander une sortie anticipée de l'application en appelant directement `exit()`)''. Enfin, la troisième partie, à droite, c'est le code des bibliothèques système utilisées par l'application, ce sont elles qui font les appels système, ici, seule la fonction `clock()` est représentée.
    31 
    32 
    33 
    34 = 1. Les modes d'exécution du MIPS
     28- En bas à gauche, c'est le code de boot qui, ici, se contente d'initialiser la pile d'exécution du noyau et d'entrer dans le noyau par la fonction `kinit()` (kernel init).  Ce code s'exécute en mode `kernel`, mais il ne fait pas partie du noyau car, dans un vrai système, il doit charger le noyau depuis le disque dur, mais, ici, le noyau est déjà en mémoire alors c'est plus simple.
     29- En bas, c'est le noyau avec la fonction `kinit()` qui initialise les structures de données internes du noyau. Ici, il s'agit juste de mettre les variables globales non initialisées à 0, puis d'appeler la routine `app_load` qui va entrer dans la première fonction de l'application utilisateur nommée `_start()`. Dans le noyau, sur la figure, on voit aussi la routine `kentry` qui est le point d'entrée du noyau pour la gestion des services. Actuellement, il n'y a que le gestionnaire d'appel système (`syscall`). Son comportement est succinctement résumé.
     30- En haut, c'est l'application utilisateur, décomposée en trois parties. La première à gauche est la fonction `_start()` appelée par le noyau au tout début de l'application. Cette fonction initialise à 0 les variables globales non initialisées dans le programme, puis elle appelle la fonction `main()`. Si on sort de la fonction `main()` avec un `return`, la fonction `_start` fait l'appel système `exit()`. La seconde partie au centre contient le code de l'utilisateur  ''(notez que la fonction `main()` ou l'une des fonctions appelées par la fonction `main()` peut demander une sortie anticipée de l'application en appelant directement `exit()`)''. Enfin, la troisième partie, à droite, c'est le code des bibliothèques système utilisées par l'application, ce sont elles qui font les appels système, ici, seule la fonction `clock()` est représentée.
     31
     32
     33
     34= 1. Les modes d'exécution du MIPS et les instructions ''système''
    3535
    3636
     
    5757''
    5858}}}
    59 1. Le MIPS propose des registres à usage général (GPR ''General Purpose Register'') pour les calculs ($0 à $31). Le MIPS propose un deuxième banc de registres à l'usage du système d'exploitation, ce sont les registres système (dans le coprocesseur 0).\\Comment sont-ils numérotés? Chaque registre porte un nom correspondant à son usage, quels sont ceux que vous connaissez: donner leur nom, leur numéro et leur rôle? Peut-on faire des calculs avec des registres? Quelles sont les instructions qui permettent de les manipuler? (C10 S5+S11)
     591. Le MIPS propose des registres à usage général (GPR ''General Purpose Register'') pour les calculs ($0 à $31).\\
     60 Le MIPS propose un deuxième banc de registres **à l'usage du système d'exploitation** dans le coprocesseur 0.\\
     61 Chaque registre **''système''** porte un nom correspondant à son usage, nous en avons vu 3 en cours (C10 S7+S10 à S14) : `c0_sr`, `c0_cause` et `c0_epc`.\\
     62 Donner leur numéro et leur rôle en une phrase ?
    6063{{{#!protected ------------------------------------------------------------------------------------
    6164''
     
    6972   || `c0_count`  || `$9 ` || contient le nombre de cycles depuis le démarrage du MIPS
    7073   || `c0_procid` || `$15` || contient le numéro du processeur (utile pour les architectures multicores)
    71 - non, il n'est pas possible de faire des calculs sur ces registres.
    72 - On peut juste les lire et les écrire en utilisant les instructions `mtc0` et `mfc0`
    73 ''
    74 }}}
    75 1. Le registre status est composé de plusieurs champs de bits qui ont chacun une fonction spécifique.\\Décrivez le contenu du registre status et le rôle des bits de l'octet 0 (seulement les bits vus en cours). (C10 S12+S13+S15)
     74''
     75}}}
     761. Les deux instructions qui permettent de les manipuler sont `mtc0` et `mfc0` (C10 S11).\\
     77 Quelle est leur syntaxe ?\\
     78 Est-ce qu'on peut manipuler ces registres **''système''** avec d'autres instructions ?\\
     79 Écrivez les instructions permettant de faire `c0_epc = c0_epc + 4` (vous utiliserez le registre GPR `$8`)
     80{{{#!protected ------------------------------------------------------------------------------------
     81''
     82  || `mtc0 $GPR, $C0` || `M`ove `T`o `C`oprocessor `0`   || `$GPR` → COPRO_0(`$C0`)
     83  || `mfc0 $GPR, $C0` || `M`ove `F`rom `C`oprocessor `0` || `$GPR` ←  COPRO_0(`$C0`)
     84- Attention à l'ordre des registres dans les instructions.\\
     85 L'ordre est toujours le même, c'est d'abord le registre $GPR puis le registre $C0, le sens de l'échange est défini par l'opcode de l'instruction (move `TO` ou move `FROM` coprocessor 0).\\
     86 `$C0`  peut être `c0_sr` (i.e. $12) ou `c0_cause` (i.e. $13) ou `c0_epc` (i.e. $14)
     87- non, il n'est pas possible d'utiliser d'autres instructions pour les manipuler, on peut juste les lire et les écrire en utilisant les instructions `mtc0` et `mfc0`\\ \\
     88- `c0_epc = c0_epc + 4`
     89{{{#!c
     90mfc0    $8, $14
     91addiu   $8, $8, 4
     92mtc0    $8, $14
     93}}}
     94''
     95}}}
     961. Le registre status est composé de plusieurs champs de bits qui ont chacun une fonction spécifique.\\Décrivez le contenu du registre status et le rôle des bits 0, 1 et 4 de l'octet 0. (C10 S12+S13+S15)
    7697{{{#!protected ------------------------------------------------------------------------------------
    7798''
    7899 || 0|| IE  ||Interrupt Enable||0 → interruptions masquées\\1 → interruptions autorisées si ERL et EXL sont tous les deux à 0
    79100 || 1|| EXL ||EXception Level ||1 → MIPS en mode exception à l'entrée dans le kernel\\le MIPS est en mode kernel, interruptions masquées
    80  || 2|| ERL ||ERror Level     ||1 → au démarrage du MIPS et certaines erreurs de la mémoire\\le MIPS est en mode kernel, interruptions masquées
    81101 || 4|| UM  ||User Mode       ||0 → MIPS en mode kernel\\1 → MIPS en mode user, seulement si ERL et EXL sont tous les deux à 0
    82102''
     
    86106''
    87107- Le champ `XCODE` qui contient le code de la cause d'entrée dans le noyau est codé sur 4 bits entre les bits 2 et 5.
    88 - Les valeurs les plus importantes sont 0 et 8 (interruption et syscall). Les autres valeurs sont des exceptions, c'est-à-dire des fautes faites par le programme.
     108- Les codes les plus importantes à connaitre sont 0 et 8 (interruption et syscall). Les autres codes sont pour les exceptions, c'est-à-dire des fautes faites par le programme.
    89109
    90110  ||0|| 0000,,b,, || interruption || un contrôleur de périphérique à lever un signal IRQ
     
    96116{{{#!protected ------------------------------------------------------------------------------------
    97117''
    98 - Une exception, c'est une erreur du programme, telle qu'une division par 0, une lecture non alignée ou une instruction illégale. Il est important que le gestionnaire d'exception sache quelle est l'instruction fautive. C'est pour cette raison que le registre EPC contient l'adresse de l'instruction fautive. Le gestionnaire pourra lire l'instruction et éventuellement corriger le problème.
     118- Une exception, c'est une erreur du programme, telle que la lecture d'un mot à une adresse non mappée, une lecture non alignée ou une instruction illégale. Il est important que le gestionnaire d'exception sache quelle est l'instruction fautive. C'est pour cette raison que le registre EPC contient l'adresse de l'instruction fautive. Le gestionnaire pourra lire l'instruction et éventuellement corriger le problème.
    99119- A titre indicatif, ce n'est pas la question, mais pour les syscall, c'est aussi l'adresse de l'instruction `syscall` qui est stockée dans `C0_EPC`, or pour le retour de `syscall`, on souhaite aller à l'instruction suivante. Il faut donc incrémenter la valeur de `C0_EPC` de 4 (les instructions font 4 octets) pour connaître l'adresse de retour.
    100120''
     
    103123{{{#!protected ------------------------------------------------------------------------------------
    104124''
    105 - Les trois instructions sont
     125- Les trois instructions sont `mtc0`, `mfc0` (déjà vues au dessus) et `eret`
    106126
    107127  || `mtc0 $GPR, $C0` || `M`ove `T`o `C`oprocessor `0`   || `$GPR` → COPRO_0(`$C0`)
     
    109129  || `eret`           || `E`xpection `RET`urn            || `PC`  ←  `EPC` ; `c0_sr.EXL`  ←  `0`
    110130
    111   Attention à l'ordre des registres dans les instructions. L'ordre est toujours le même, c'est d'abord le registre $GPR puis le registre $C0, le sens de l'échange est défini par l'opcode de l'instruction (move `TO` ou move `FROM` coprocessor 0).
    112131- Bien sûr que `syscall` peut être utilisé en mode user, puisque c'est comme ça qu'on entre dans le kernel pour les demandes de services.
    113132''