Changes between Version 127 and Version 128 of Archi-1-TP10
- Timestamp:
- Nov 19, 2023, 10:39:15 AM (12 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Archi-1-TP10
v127 v128 22 22 23 23 24 Le TP est découpé en 4 é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. 24 Le TP est découpé en 4 étapes. Pour chaque étape, nous donnons : 25 1. une brève description avec une liste des objectifs principaux de l'étape, 26 2. une liste des fichiers avec un bref commentaire sur chaque fichier, 27 3. une liste de questions simples dont les réponses sont dans le code, le cours ou le TD, 4 28 4. un petit exercice de codage. 25 29 26 30 **IMPORTANT\\Avant de faire cette séance, vous devez avoir regardé les documents suivants** : … … 29 33 > * [htdocs:cours/Archi-1-C9-outils-annexe-2p.pdf Éléments d'information sur les outils de la chaîne de compilation] ''recommandé'' 30 34 > * [htdocs:cours/doc_MIPS32.pdf Document sur l'assembleur du MIPS et la convention d'appel des fonctions] : ''recommandé, mais déjà lu'' 31 > * [wiki:Doc-MIPS-Archi-Asm-kernel Documentation sur le mode kernel du MIPS32] : ''obligatoire ''35 > * [wiki:Doc-MIPS-Archi-Asm-kernel Documentation sur le mode kernel du MIPS32] : ''obligatoire pour compléter le cours'' 32 36 33 37 … … 57 61 Les applications de l'utilisateur s'exécutent en mode user. Dans la séance précédente, nous avons vu que les registres de commande des contrôleurs de périphériques sont placés dans l'espace d'adressage du processeur. Les adresses de ces registres ont été placées dans la partie de l'espace d'adressage interdite en mode user. Ainsi, une application n'a pas un accès direct aux périphériques, elle doit utiliser des appels système (avec l'instruction `syscall`) pour demander au noyau du système d'exploitation de faire l'accès. C'est ce que nous allons voir. 58 62 59 Le code est désormais découpé en 4 étapes : 60 - **`1_klibc`**\\⟶ Le code de boot et `kinit()` avec une librairie de fonctions standard pour le noyau;61 - **`2_appk`**\\⟶ La fonction d'initialisation `kinit()` appelle une application mais le noyau n'a pas encore le gestionnaire des appels systèmes;62 - **`3_syscalls`**\\⟶ Ajout du gestionnaire des appels système et une application **sans** la librairie de fonctions standards utilisateur (libc);63 - **`4_libc`**\\⟶ Ajout d e la libc (rudimentaire) et d'une application.63 Vous allez suivre 4 étapes : 64 - **`1_klibc`**\\⟶ Ajout d'une librairie de fonctions standards pour le noyau (klibc), mais pas d'application utilisateur ; 65 - **`2_appk`**\\⟶ Appel d'une application utilisateur par la fonction d'initialisation `kinit()`, mais sans gestionnaire des appels systèmes dans le noyau, il n'est donc pas possible d'utiliser `syscall` ; 66 - **`3_syscalls`**\\⟶ Ajout du gestionnaire des appels système et une application, mais **sans** la librairie de fonctions standards utilisateur (libc); 67 - **`4_libc`**\\⟶ Ajout d'une librairie de fonctions standards utilisateur minimaliste (libc) et d'une application. 64 68 65 69 66 70 Pour les travaux pratiques, vous devez d'abord répondre aux questions, elles ont pour but de vous faire lire le code et revoir les points du cours et vous guidez, un peu, pour l'exercice. Les réponses sont dans le cours ou dans les fichiers sources. Certaines ont déjà été traitées en TD, c'est normal. Ensuite, vous passez aux exercices pratiques. 67 71 68 Le code se trouve dans `kO6/tp2/`, ouvrez un terminal et allez-y. Dans ce répertoire, vous avez 4 sous-répertoires et un Makefile. Le fichier `kO6/tp2/Makefile`permet de faire le ménage en appelant les Makefiles des sous-répertoires avec la cible `clean`.72 Le code se trouve normalement dans `kO6/tp2/` (sinon téléchargez-le), ouvrez un terminal et allez-y. Dans ce répertoire, vous avez 4 sous-répertoires et un Makefile. Le fichier `kO6/tp2/Makefile` qui fait un appel récursif à `make` et qui permet de faire le ménage en appelant les Makefiles des sous-répertoires avec la cible `clean`. 69 73 70 74 … … 76 80 **Objectifs de l'étape** 77 81 78 Le noyau gère les ressources matérielles et logicielles utilisées par les applications. Il a besoin de fonctions standards pour réaliser des opérations de base, telles qu'une fonction `print` ou une fonction `rand` . Ces fonctions ne sont pas très originales, mais elles recèlent des subtilités que vous ne connaissez peut-être pas encore, vous pouvez les regarder par curiosité. En outre, nous allons utiliser un Makefile définissant un graphe de dépendance explicite entre les fichiers cibles et les fichiers sources avec des règles de construction.82 Le noyau gère les ressources matérielles et logicielles utilisées par les applications. Il a besoin de fonctions standards pour réaliser des opérations de base, telles qu'une fonction `print` ou une fonction `rand` (générateur de nombres pseudo-aléatoires). Ces fonctions ne sont pas très originales, mais elles recèlent des subtilités que vous ne connaissez peut-être pas encore, vous pouvez les regarder par curiosité, même si ce n'est pas le but du TP. En outre, nous allons utiliser un Makefile définissant un graphe de dépendance explicite entre les fichiers cibles et les fichiers sources avec des règles de construction. 79 83 80 84 … … 99 103 100 104 101 1. Ouvrez le fichier Makefile (vous pouvez regarder les dépendances en ouvrant quelques fichiers sources), puis dessiner le graphe de dépendance de `kernel.x` vis-à-vis de ses sources?\\La réponse peut-être visible avec la commande `dot -Tpng Makefile.dot -oMakefile.png` à partir du fichier `Makefile.dot` reproduit ci-après (dot est un outil de [https://www.graphviz.org graphviz] ... essayez c'est magique :-)\\ \\`Makefile.dot`105 1. Ouvrez le fichier Makefile (vous pouvez regarder les dépendances en ouvrant quelques fichiers sources), puis dessiner le graphe de dépendance de `kernel.x` vis-à-vis de ses sources?\\La réponse peut-être visible avec la commande `dot -Tpng Makefile.dot -oMakefile.png` à partir du fichier `Makefile.dot` reproduit ci-après ''(`dot` est un outil de [https://www.graphviz.org graphviz] ... essayez c'est magique :-)'' \\ \\`Makefile.dot` 102 106 {{{#!c 103 107 digraph G { … … 139 143 140 144 141 * Le numéro du processeur est dans les 12 bits de poids faible du registre $15 (`c0_cpuid`) du coprocesseur système (à côté des registres `c0_epc`, `c0_sr`, etc.). Ajoutez la fonction `int cpuid(void)` qui lit le registre `c0_cpuid` et qui rend un entier contenant juste les 12 bits de poids faible.\\Vous pouvez vous inspirez fortement de la fonction `int clock(void)`. Comme il n'y a qu'un seul processeur dans cette architecture, `cpuid` rend toujours `0`.\\Ecrivez un programme de test (vous devrez modifier les fichiers `hcpu.h`, `hcpua.S` et `kinit.c`)145 * Le numéro du processeur est dans les 12 bits de poids faible du registre du **coprocesseur 0 $15** (`c0_cpuid`) (à côté des registres `c0_epc`, `c0_sr`, etc. ce n'est pas le registre GPR $15). Ajoutez la fonction `int cpuid(void)` qui lit le registre `c0_cpuid` et qui rend un entier contenant juste les 12 bits de poids faible.\\Vous pouvez vous inspirez fortement de la fonction `int clock(void)`. Comme il n'y a qu'un seul processeur dans cette architecture, `cpuid` rend toujours `0`.\\Ecrivez un programme de test (vous devrez modifier les fichiers `hcpu.h` pour y mettre le prototype de la fonction, `hcpua.S` pour y mettre le code et `kinit.c` pour appeler la fonction) 142 146 143 147 {{{#!protected … … 170 174 Nous allons désormais avoir deux exécutables: le noyau et l'application. Dans cette étape, nous allons voir comment le noyau fait pour appeler l'application, alors même que celle-ci n'est pas compilée en même temps que le noyau. Nous allons passer du noyau à l'application à la fin de la fonction `kinit()`. 171 175 172 Nous allons donc entrer dans l'application, en revanche, dans cette étape, nous n'allons pas mettre en place la gestion des syscalls. **C'est-à-dire qu'il ne sera pas possible de revenir dans le noyau depuis l'application**. C'est bien entendu une étape intermédiaire, parce qu'il faut absolument pouvoir invoquer le noyau depuis l'application pour accéder aux périphériques. 173 Pour pouvoir quand même accéder aux registres de périphériques, nous allons **exceptionnellement** exécuter l'application en mode kernel. Ainsi, l'application pourra accéder aux adresses de l'espace d'adressage réservées au mode `kernel`. 176 Nous allons donc entrer dans l'application, en revanche, dans cette étape, nous n'allons pas mettre en place la gestion des syscalls. **C'est-à-dire qu'il ne sera pas possible de revenir dans le noyau depuis l'application**. C'est bien entendu une étape intermédiaire, parce qu'il faudra absolument pouvoir invoquer le noyau depuis l'application pour accéder aux périphériques.\\**Pour pouvoir quand même accéder aux registres de périphériques, nous allons EXCEPTIONNELLEMENT exécuter l'application en mode kernel. Ainsi, l'application pourra accéder aux adresses de l'espace d'adressage réservées au mode `kernel`.** 174 177 175 178 Nous avons deux exécutables à compiler et donc deux `Makefile`s de compilation. Nous avons aussi un `Makefile` qui invoque récursivement les `Makefile`s de compilation.