Changes between Version 127 and Version 128 of Archi-1-TP10


Ignore:
Timestamp:
Nov 19, 2023, 10:39:15 AM (12 months ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TP10

    v127 v128  
    2222
    2323
    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.
     24Le TP est découpé en 4 étapes. Pour chaque étape, nous donnons :
     251. une brève description avec une liste des objectifs principaux de l'étape,
     262. une liste des fichiers avec un bref commentaire sur chaque fichier,
     273. une liste de questions simples dont les réponses sont dans le code, le cours ou le TD, 4
     284. un petit exercice de codage.
    2529
    2630**IMPORTANT\\Avant de faire cette séance, vous devez avoir regardé les documents suivants** :
     
    2933> * [htdocs:cours/Archi-1-C9-outils-annexe-2p.pdf Éléments d'information sur les outils de la chaîne de compilation] ''recommandé''
    3034> * [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''
    3236
    3337
     
    5761Les 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.
    5862
    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 de la libc (rudimentaire) et d'une application.
     63Vous 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.
    6468
    6569
    6670Pour 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.
    6771
    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`.
     72Le 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`.
    6973
    7074
     
    7680**Objectifs de l'étape**
    7781
    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.
     82Le 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.
    7983
    8084
     
    99103
    100104
    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`
     1051. 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`
    102106{{{#!c
    103107digraph G {
     
    139143
    140144
    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)
    142146
    143147{{{#!protected
     
    170174Nous 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()`.
    171175
    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`.
     176Nous 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`.**
    174177
    175178Nous 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.