Changes between Version 27 and Version 28 of Archi-1-TP10
- Timestamp:
- Jan 2, 2021, 10:10:05 AM (4 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Archi-1-TP10
v27 v28 126 126 ''''''''''''''' 127 127 }}} 128 1. Le registre `EPC` est un registre 32 bits qui contient une adresse. Vous devriez l'avoir décrit dans la question 2, mais expliquez pourquoi ce doit être l'adresse de l'instruction qui provoque une exception qui doit être stocké dans `EPC`?128 1. Le registre `EPC` est un registre 32 bits qui contient une adresse. Vous devriez l'avoir décrit dans la question 2, mais expliquez pourquoi ce doit être l'adresse de l'instruction qui provoque une exception qui doit être stockée dans `EPC`? 129 129 {{{#!protected ------------------------------------------------------------------------------------ 130 130 ''''''''''''''' … … 147 147 {{{#!protected ------------------------------------------------------------------------------------ 148 148 ''''''''''''''' 149 - C'est `0x80000180`i. Il n'y a qu'un adresse pour toutes les causes syscall, exception et interruption.149 - C'est `0x80000180`i. Il n'y a qu'une adresse pour toutes les causes syscall, exception et interruption. 150 150 - En fait, on peut considérer que `0xBFC00000` permet aussi d'entrer dans le noyau après un reset. 151 151 ''''''''''''''' … … 185 185 {{{#!protected ------------------------------------------------------------------------------------ 186 186 ''''''''''''''' 187 - `__attribute__ ((section (".crt0")))`. Remarquez la syntaxe un peu curieuse avec les doubles underscore et les doubles parenthèse .187 - `__attribute__ ((section (".crt0")))`. Remarquez la syntaxe un peu curieuse avec les doubles underscore et les doubles parenthèses. 188 188 ''''''''''''''' 189 189 }}} … … 211 211 ''''''''''''''' 212 212 - La ligne 11 contient `. = ALIGN(4)`, c'est équivalent à la directive `.align 4` de l'assembleur. 213 cela permet de déplacer le pointeur de remplissage de la section de sortie courante (c'est-à-dire ici `.kdata`)214 frontière de 2^4^ octets (une adresse multiple de 16). Cette contrainte est lié aucaches que nous ne verrons pas ici.213 Cela permet de déplacer le pointeur de remplissage de la section de sortie courante (c'est-à-dire ici `.kdata`) 214 frontière de 2^4^ octets (une adresse multiple de 16). Cette contrainte est liée aux caches que nous ne verrons pas ici. 215 215 - La ligne 12 permet de créer la variable de ldscript `__bss_origin` et de l'initialiser à l'adresse courante, 216 ce sera donc l'adresse de début d ula zone `bss`.216 ce sera donc l'adresse de début de la zone `bss`. 217 217 - La ligne 15 permet de créer la variable `__bss_end` qui sera l'adresse de fin de la zone `bss` 218 218 (en fait c'est la première adresse qui suit juste `bss`. … … 239 239 - `extern` : informe le compilateur que la variable définie existe ailleurs. Grâce à son type, le compilateur sait s'en servir. 240 240 - `volatile` : informe le compilateur que la variable peut changer de valeur toute seule et que donc il doit toujours accéder en mémoire à chaque fois que le programme le demande. Il ne peut donc pas optimiser les accès mémoire en utilisant les registres. 241 - `__tty_regs_map` est un tableau à 2 cases (puisque `NTTYS`=2). Chaque case est une structure de 4 entiers, donc `0x10` octets. `read` est le troisième champ s, c'est le troisième entier de la structure, donc en `+8` par rapport au début.\\En conséquence `__tty_regs_map[1].read` est en `0xd0200018`242 ''''''''''''''' 243 }}} 244 1. Certaines parties du noyau sont en assembleur. Il y a u moins les toutes premières instructions du code de boot (démarrage de l'ordinateur) et l'entrée dans le noyau après l'exécution d'un syscall. Dans ce dernier cas, le gestionnaire de syscall écrit en assembleur a besoin d'appeler une fonction écrite en langage C. Le gestionnaire de syscall trouve l'adresse de la fonction C qu'il doit appeler puis il place cette adresse dans un registre, par exemple `$2`. Il suffit qu'il exécute l'instruction `jal $2` pour appeler la fonction. Que doivent contenir les registres `$4` à `$7` et comment doit-être la pile?241 - `__tty_regs_map` est un tableau à 2 cases (puisque `NTTYS`=2). Chaque case est une structure de 4 entiers, donc `0x10` octets. `read` est le troisième champ, c'est le troisième entier de la structure, donc en `+8` par rapport au début.\\En conséquence `__tty_regs_map[1].read` est en `0xd0200018` 242 ''''''''''''''' 243 }}} 244 1. Certaines parties du noyau sont en assembleur. Il y a au moins les toutes premières instructions du code de boot (démarrage de l'ordinateur) et l'entrée dans le noyau après l'exécution d'un syscall. Dans ce dernier cas, le gestionnaire de syscall écrit en assembleur a besoin d'appeler une fonction écrite en langage C. Le gestionnaire de syscall trouve l'adresse de la fonction C qu'il doit appeler puis il place cette adresse dans un registre, par exemple `$2`. Il suffit qu'il exécute l'instruction `jal $2` pour appeler la fonction. Que doivent contenir les registres `$4` à `$7` et comment doit-être la pile? 245 245 {{{#!protected ------------------------------------------------------------------------------------ 246 246 ''''''''''''''' 247 247 - C'est un appel de fonction, il faut donc respecter la convention d'appel des fonctions 248 - Les registre `$4`à `$7` contiennent les arguments de la fonction248 - Les registres `$4`à `$7` contiennent les arguments de la fonction 249 249 - Le pointeur de pile doit pointer sur la case réservée pour le premier argument et les cases suivantes sont réservées 250 250 arguments suivants. … … 253 253 ''''''''''''''' 254 254 }}} 255 1. Vous avez appris à écrire des programmes assembleur, mais parfois il est plus simple, voire il est nécessaire de mélanger le code C et le code assembleur. Dans l'exemple ci-dessous, nous voyons comment la fonction `kinit()` procède pour entrer dans la fonction placée à l'adresse `__crt0` définie dans le fichier `kernel.ld`. Remarquez la syntaxe, ici `volatile` permet de dire au compilateur d'insérer le code tel que sans le modifier. Notez aussi l'absence de `,` entre les chaînes de caractères. Le premier argument de `__asm__` est une chaîne de caractères unique dans laquelle les instructions sont séparées par de `\n`. Il peut y avoir d'autres arguments, nous ne les verrons pas.\\Dans quelle section se trouve l'adresse `__crt0`? Combien vaut elle? Est-ce que cette valeur est imposée par le processeur MIPS comme l'adresse de boot ou d'entrée dans le kernel? Quelle fonction est à cette adresses? Pourquoi doit-on écrire ce code en assembleur?255 1. Vous avez appris à écrire des programmes assembleur, mais parfois il est plus simple, voire il est nécessaire de mélanger le code C et le code assembleur. Dans l'exemple ci-dessous, nous voyons comment la fonction `kinit()` procède pour entrer dans la fonction placée à l'adresse `__crt0` définie dans le fichier `kernel.ld`. Remarquez la syntaxe, ici `volatile` permet de dire au compilateur d'insérer le code tel que sans le modifier. Notez aussi l'absence de `,` entre les chaînes de caractères. Le premier argument de `__asm__` est une chaîne de caractères unique dans laquelle les instructions sont séparées par de `\n`. Il peut y avoir d'autres arguments, nous ne les verrons pas.\\Dans quelle section se trouve l'adresse `__crt0`? Combien vaut-elle? Est-ce que cette valeur est imposée par le processeur MIPS comme l'adresse de boot ou d'entrée dans le kernel? Quelle fonction est à cette adresse? Pourquoi doit-on écrire ce code en assembleur? 256 256 {{{#!c 257 257 9 void kinit (void) … … 329 329 ''''''''''''''' 330 330 }}} 331 1. Nous avons vu que le noyau est sollicité par des événements, quels sont-ils?Quel est le comportement exact de l'instruction `syscall`? Comment le noyau fait-il pour conna itre la cause de son appel?331 1. Nous avons vu que le noyau est sollicité par des événements, quels sont-ils?Quel est le comportement exact de l'instruction `syscall`? Comment le noyau fait-il pour connaître la cause de son appel? 332 332 {{{#!protected ------------------------------------------------------------------------------------ 333 333 ''''''''''''''' … … 339 339 ''''''''''''''' 340 340 }}} 341 1. `$26` et `$27` sont deux registres temporaires que le noyau se réserve pour faire des calcul sans qu'il ait besoin de les sauvegarder dans la pile. Ce ne sont pas des registres système comme `c0_sr` ou `c0_epc`. En effet l'usage de `$26` et `$27` par l'utilisateur ne provoque pas d'exception du MIPS, mais si le noyau est appelé, il modifie ces registres et donc l'utilisateur perd leur valeur. Le code assembleur ci-après contient les instructions exécutées par le noyau quelque-soit la cause. Les commentaires présents dans le code ont été volontairement retirés. La section `.kentry` sera placée à l'adresse `0x80000000` par l'éditeur de lien. La directive `.org` (ligne 16) permet de déplacer le pointeur de remplissage de la section courante du nombre d'octets donnés en argument, ici `0x180`. Pouvez-vous dire pourquoi ? Expliquer les lignes 25 à 28.\\ \\**`kernel/hcpu.S`**341 1. `$26` et `$27` sont deux registres temporaires que le noyau se réserve pour faire des calculs sans qu'il ait besoin de les sauvegarder dans la pile. Ce ne sont pas des registres système comme `c0_sr` ou `c0_epc`. En effet l'usage de `$26` et `$27` par l'utilisateur ne provoque pas d'exception du MIPS, mais si le noyau est appelé, il modifie ces registres et donc l'utilisateur perd leur valeur. Le code assembleur ci-après contient les instructions exécutées par le noyau, quelle que soit la cause. Les commentaires présents dans le code ont été volontairement retirés. La section `.kentry` sera placée à l'adresse `0x80000000` par l'éditeur de lien. La directive `.org` (ligne 16) permet de déplacer le pointeur de remplissage de la section courante du nombre d'octets donnés en argument, ici `0x180`. Pouvez-vous dire pourquoi ? Expliquer les lignes 25 à 28.\\ \\**`kernel/hcpu.S`** 342 342 {{{#!c 343 343 15 .section .kentry,"ax" … … 416 416 {{{#!protected ------------------------------------------------------------------------------------ 417 417 ''''''''''''''' 418 - Le rôle principal d'un Makefile est de décrire le mode d'emploi pour construire un fichier dit **`cible`** à partir d'un ou plusieurs fichiers **`source`** dit de dépendance en utilisant des commandes du `shell`. Ce rôle pourrait tout aussi bien être occupé par un script `shell` et d'ailleurs dans le premier TP nous avons vu un usage du Makefile dans lequel nous avions rassemblerplusieurs scripts `shell` sous forme de règles.419 - Le second rôle d'un Makefile est de permettre la reconstruction efficace du fichier **`cible`** lorsqu'un seul seul fichier **`source`** change. Pour ce rôle, le Makefile exprime toutes les étapes de constructions de la **`cible`** finale et des **`cibles`** intermédiaires sous forme d'un arbre dont les feuilles sont les fichiers **`source `**.420 ''''''''''''''' 421 }}} 422 1. Vous n'allez pas à avoir à écrire un Makefile complètement, toutefois vous allez devoir les modifier en ajoutant des règles. Nous avons vu brièvement la syntaxe utilisée dans les Makefiles de ce TP au cours n°1. Les lignes qui suivent sont des extraits du premier Makefile. Quelles est la cible finale, les cibles intermédiaires et les sources? A quoi servent les variables automatiques de make? Dans ces deux règles, donnez-en la valeur.418 - Le rôle principal d'un Makefile est de décrire le mode d'emploi pour construire un fichier dit **`cible`** à partir d'un ou plusieurs fichiers **`source`** dits de dépendance en utilisant des commandes du `shell`. Ce rôle pourrait tout aussi bien être occupé par un script `shell` et d'ailleurs dans le premier TP nous avons vu un usage du Makefile dans lequel nous avions rassemblé plusieurs scripts `shell` sous forme de règles. 419 - Le second rôle d'un Makefile est de permettre la reconstruction efficace du fichier **`cible`** lorsqu'un seul seul fichier **`source`** change. Pour ce rôle, le Makefile exprime toutes les étapes de constructions de la **`cible`** finale et des **`cibles`** intermédiaires sous forme d'un arbre dont les feuilles sont les fichiers **`sources`**. 420 ''''''''''''''' 421 }}} 422 1. Vous n'allez pas à avoir à écrire un Makefile complètement, toutefois vous allez devoir les modifier en ajoutant des règles. Nous avons vu brièvement la syntaxe utilisée dans les Makefiles de ce TP au cours n°1. Les lignes qui suivent sont des extraits du premier Makefile. Quelles sont la cible finale, les cibles intermédiaires et les sources? A quoi servent les variables automatiques de make? Dans ces deux règles, donnez-en la valeur. 423 423 {{{#!make 424 424 kernel.x : kernel.ld obj/hcpu.o obj/kinit.o obj/klibc.o obj/harch.o … … 435 435 ''''''''''''''' 436 436 }}} 437 1.Dans le TP, apartir de la deuxième étape, nous avons trois répertoire de sources437 1.Dans le TP, à partir de la deuxième étape, nous avons trois répertoire de sources 438 438 {{{ 439 439 4_libc/ 440 440 ├── Makefile : Makefile racine qui invoque les Makefiles des sous-répertoires et qui exécute 441 ├── common ────────── répe toire des fichiers commun kernel / user441 ├── common ────────── répertoire des fichiers commun kernel / user 442 442 ├── kernel ────────── Répertoire des fichiers composant le kernel 443 443 │ └── Makefile : description des actions possibles sur le code kernel : compilation et nettoyage … … 472 472 ''''''''''''''' 473 473 }}} 474 1. génération de nombres pseudo -aléatoire`rand`?474 1. génération de nombres pseudoaléatoires `rand`? 475 475 {{{#!protected ------------------------------------------------------------------------------------ 476 476 ''''''''''''''' … … 500 500 501 501 502 == B1. Ajout d'une bibliothèque de fonctions standard pour le kernel (klic)503 504 505 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. En outre, nous allons utiliser un Makefile définissant un graphe de dépendance explicite entre les fichiers cibles et les fichiers source avec des règles de construction.502 == B1. Ajout d'une bibliothèque de fonctions standards pour le kernel (klic) 503 504 505 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. 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. 506 506 507 507 … … 582 582 │ └── Makefile : description des actions possibles sur le code kernel : compilation et nettoyage 583 583 └── user ──────────── Répertoire des fichiers composant l'application user 584 ├── crt0.c : fonctions d'interface entre kernel et user, pour le mom ment : crt0()584 ├── crt0.c : fonctions d'interface entre kernel et user, pour le moment : crt0() 585 585 ├── main.c : fonction principale de l'application 586 586 ├── user.ld : ldscript décrivant l'espace d'adressage pour l'édition de liens du user … … 614 614 3_syscalls/ 615 615 ├── Makefile : Makefile racine qui invoque les Makefiles des sous-répertoires et qui exécute 616 ├── common ────────── répe toire des fichiers commun kernel / user616 ├── common ────────── répertoire des fichiers commun kernel / user 617 617 │ └── syscalls.h : API la fonction syscall et des codes de syscalls 618 618 ├── kernel ────────── Répertoire des fichiers composant le kernel … … 630 630 │ └── Makefile : description des actions possibles sur le code kernel : compilation et nettoyage 631 631 └── user ──────────── Répertoire des fichiers composant l'application user 632 ├── crt0.c : fonctions d'interface entre kernel et user, pour le mom ment : crt0()632 ├── crt0.c : fonctions d'interface entre kernel et user, pour le moment : crt0() 633 633 ├── main.c : fonction principale de l'application 634 634 ├── user.ld : ldscript décrivant l'espace d'adressage pour l'édition de liens du user … … 660 660 4_libc/ 661 661 ├── Makefile : Makefile racine qui invoque les Makefiles des sous-répertoires et qui exécute 662 ├── common ────────── répe toire des fichiers commun kernel / user662 ├── common ────────── répertoire des fichiers commun kernel / user 663 663 │ └── syscalls.h : API la fonction syscall et des codes de syscalls 664 664 ├── kernel ────────── Répertoire des fichiers composant le kernel … … 679 679 │ └── Makefile : description des actions possibles sur le code user : compilation et nettoyage 680 680 └── ulib ──────────── Répertoire des fichiers des bibliothèques système liés avec l'application user 681 ├── crt0.c : fonctions d'interface entre kernel et user, pour le mom ment : crt0()681 ├── crt0.c : fonctions d'interface entre kernel et user, pour le moment : crt0() 682 682 ├── libc.h : API pseudo-POSIX de la bibliothèque C 683 683 ├── libc.c : code source de la libc