[[PageOutline]] {{{#!html

Boot et premier programme en mode kernel

}}} Si ce n'est pas encore fait, vous devez lire la page décrivant les [WikiStart#obj_gen objectifs généraux] des séances, le [WikiStart#prin_peda principe pédagogique] choisi et le [WikiStart#fonc_sean fonctionnement des séances]. La séance est découpé en 5 étapes. Dans cette présentation, pour chaque étape, nous donnons une brève description, suivie d'une liste des objectifs principaux et d'une liste des fichiers présents. Un bref commentaire est ajouté pour les fichiers. = 1. Premier programme en assembleur dans la seule section de boot**= Nous commençons par un petit programme de quelques lignes en assembleur, placé entièrement dans la région mémoire du boot, qui réalise l'affichage du message "Hello World". C'est un tout tout petit programme, mais pour obtenir l'exécutable, vous devrez utiliser tous les outils de la chaîne de cross-compilation MIPS et pour l'exécuter vous devrez exécuter le simulateur du prototype. C'est simple, mais c'est nouveau pour beaucoup d'entre vous. - **Objectifs**\\\\ - produire un exécutable à partir d'un code en assembleur. - savoir comment afficher un caractère sur un terminal. - analyse d'une trace d'exécution - **Fichiers** {{{ 1_hello_boot ├── hcpu.S : code dépendant du cpu matériel en assembleur ├── kernel.ld : ldscript décrivant l'espace d'adressage pour l'éditeur de lien └── Makefile : description des actions possibles sur le code : compilation, exécution, nettoyage, etc. }}} - **Questions**\\ ''Les réponse sont dans le cours ou dans les fichiers sources''\\\\ - Dans quel fichier se trouve la description de l'espace d'adressage du MIPS ? Que trouve-t-on dans ce fichier ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - C'est dans le fichier kernel.ld. On y trouve: - la définition de variable du ldscript. Ce sont essentiellement des adresses dans l'espace d'adressage, mais pas seulement, il y a aussi la taille des régions. - On trouve ensuite la déclaration des régions mémoire. - et enfin la définition des sections de sortie qui seront mise dans le fichier binaire produit et dans quelle région elle sont placées. ''''''''''''''' }}} - Dans quel fichier se trouve le code de boot et pourquoi l'avoir nommé ainsi ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - Le code de boot est dans le fichier `hcpu.S`. Il a a été nommé ainsi parce que c'est du code qui dépend du hardware et qu'il concerne le cpu. ''''''''''''''' }}} - A quelle adresse démarre le MIPS ? Où peut-on le vérifier ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - L'adresse de démarrage est `0xBFC00000`. - On peut le vérifier dans le fichier `kernel.ld`. Il y a une définition des régions mémoire dont une région commençant à cette adresse là et c'est dans cette région que l'on met le code de boot. ''''''''''''''' }}} - Que produit `gcc` quand on utilise l'option `-c` ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - L'option `-c` demande à `gcc` de s'arrêter après avoir produit le fichier objet. - Il produit donc un fichier au format `.o` ''''''''''''''' }}} - Que fait l'éditeur de liens ? Comment est-il invoqué ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - L'éditeur de liens rassemble toutes les sections produites par le compilateur, et donc présentes dans les fichiers objet `.o`, et il les place dans de nouvelles sections, elles-mêmes placées dans les régions de la mémoire, conformément au fichier ldscript (ici `kernel.ld`). - L'éditeur de liens est appelé par `gcc` si on n'a pas l'option `-c`ou directement par `ld` (ici `mipsel_unknown_ld`) ''''''''''''''' }}} - De quels fichiers a besoin l'éditeur de liens pour fonctionner ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - L'éditeur de liens a besoin des fichiers objets `.o` et du fichier ldscript (ici, `kernel.ld`) ''''''''''''''' }}} - Dans quelle section se trouve le code de boot pour le compilateur ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Dans quelle section se trouve le message hello pour le compilateur ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Dans quelle section se trouve le code de boot dans le code exécutable ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Dans quelle région de la mémoire le code de boot est placé ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Comment connaît-on l'adresse du registre de sortie du contrôleur de terminal TTY ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Comment sait-on que le message est fini et que le programme doit s'arrêter ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} - Pourquoi terminer le programme par un `dead: j dead` ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' ''''''''''''''' }}} = 2. Saut dans le code du noyau en assembleur Dans le deuxième programme, nous restons en assembleur, mais nous avons deux fichiers source : (1) le fichier contenant le code de boot et (2) le fichier contenant le code du noyau. Ici, le code du noyau c'est juste une ''fonction'' `kinit()`. Ce n'est pas vraiment une fonction car on n'utilise pas la pile. \\\\ **Objectifs** - Savoir comment le programme de boot fait pour sauter à l'adresse de la routine kinit. - Savoir un fichier kernel.ld un peu plus complet. **Fichiers** {{{ 2_init_asm/ ├── hcpu.S : code dépendant du cpu matériel en assembleur ├── kernel.ld : ldscript décrivant l'espace d'adressage pour l'éditeur de lien ├── kinit.S : fichier contenant le code de démarrage du noyau, ici c'est une routine kinit. └── Makefile : description des actions possibles sur le code : compilation, exécution, nettoyage, etc. }}} - **Questions**\\ ''Les réponse sont dans le cours ou dans les fichiers sources''\\\\ - Question ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - Réponse ''''''''''''''' }}} = 3. Saut dans la fonction kinit() du noyau en langage C Dans ce troisième programme, nous faisons la même chose que pour le deuxième mais `kinit()` est désormais écrit en langage C. Cela change peu de choses, sauf une chose importante `kinit()` est une fonction et donc il faut absolument une pile d'exécution. \\\\ **Objectifs** - Savoir comment et où déclarer la pile d'exécution du noyau. - Savoir comment afficher un caractère sur un terminal depuis un programme C. **Fichiers** {{{ 3_init_c/ ├── hcpu.S : code dépendant du cpu matériel en assembleur ├── kernel.ld : ldscript décrivant l'espace d'adressage pour l'éditeur de lien ├── kinit.c : fichier en C contenant le code de démarrage du noyau, ici c'est la fonction kinit(). └── Makefile : description des actions possibles sur le code : compilation, exécution, nettoyage, etc. }}} - **Questions**\\ ''Les réponse sont dans le cours ou dans les fichiers sources''\\\\ - Question ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - Réponse ''''''''''''''' }}} = 4. Accès aux registres de contrôle des terminaux TTY Le prototype de SoC que nous utilisons pour les TP est configurable. Il est possible par exemple de choisir le nombre terminaux texte (TTY). Par défaut, il y en a un mais, nous pouvons en avoir jusqu'à 4. Nous allons modifier le code du noyau pour s'adapter à cette variabilité. En outre, pour le moment, nous ne faisions qu'écrire sur le terminal, maintenant, nous allons aussi lire le clavier. \\\\ **Objectifs** - Savoir comment compiler un programme C avec du code conditionnel. - Savoir comment décrire en C l'ensemble des registres d'un contrôleur de périphérique et y accéder. **Fichiers** {{{ 4_nttys/ ├── hcpu.S : code dépendant du cpu matériel en assembleur ├── kernel.ld : ldscript décrivant l'espace d'adressage pour l'éditeur de lien ├── kinit.c : fichier en C contenant le code de démarrage du noyau, ici c'est la fonction kinit(). └── Makefile : description des actions possibles sur le code : compilation, exécution, nettoyage, etc. }}} - **Questions**\\ ''Les réponse sont dans le cours ou dans les fichiers sources''\\\\ - Question ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - Réponse ''''''''''''''' }}} = 5. Premier petit pilote pour le terminal Dans l'étape 4, nous accédons au registre de périphérique directement dans la fonction `kinit()`, ce n'est pas très simple. C'est pourquoi, nous allons ajouter un niveau d'abstraction qui représente un début de pilote de périphérique (device driver). Ce pilote, même tout petit constitue une couche logicielle avec une API. \\\\ **Objectifs** - Savoir comment créér uun début de pilote pour le terminal TTY. - Savoir comment décrire une API en C **Fichiers** {{{ 5_driver/ ├── harch.c : code dépendant de l'architecture du SoC, pour le moment c'est juste le pilote du TTY ├── harch.h : API du code dépendant de l'architecture ├── hcpu.S : code dépendant du cpu matériel en assembleur ├── kernel.ld : ldscript décrivant l'espace d'adressage pour l'éditeur de lien ├── kinit.c : fichier en C contenant le code de démarrage du noyau, ici c'est la fonction kinit(). └── Makefile : description des actions possibles sur le code : compilation, exécution, nettoyage, etc. }}} - **Questions**\\ ''Les réponse sont dans le cours ou dans les fichiers sources''\\\\ - Question ? {{{#!protected ------------------------------------------------------------------------------------ ''''''''''''''' - Réponse ''''''''''''''' }}} - Quel est le nom de la directive assembleur permettant de déclarer une section