# TP1 du boot au 1er prog user
[toc]
## Auteurs
- ZHANG han
- DZHALILOVA Alisa
## Réponses aux questions du TD et du TP
### A1 Analyse de l'architecture
- q1: différences entre RAM(Random-access memory) et ROM(Read-only memory)
- le contenu du ROM pour lire seulement. RAM utilise mémoire vivante et on peut lire et modifier son contenu.
- q2: l'espace d'adressage du MIPS, et Quelle taille fait-il
- Les adressages sont sur 32 bits. Il y a donc 2<sup>32</sup> bits.
- on peut utiliser les adresses par les instructions load et store(lw, lb, sw, sb).
- q3: l'espace d'adressage de l'application
- C'est la même chose que l'adressage du MIPS.
- q4: Dans quel composant matériel se trouve le code de démarrage
- Dans le boot situé dans la mémoire de ROM.
- C'est dans BFC00000.
- **q5**: composant qui faire des entrées sortie et d'autres composants qui pourraient être présents dans un autre SoC
- TTY fait des entrées et sorties.
- Contrôleur de disque, vidéo ou Ethernet.
- **q6**:l'espace d'adressage de TTY;
- A partir de 0x D020 0000.
MIPS peut les utiliser dans add ou etc?
- Non, seulement pour **load and store**.
le registre pour envoyer des caractères
- TTY_WRITE ( dans le format ASCII)
Que contiennent les registres TTY_STATUS et TTY_READ
- Si un lettre tapé en clavier est lue, TTY_STATUS contient 1 et son code d'ASCII est placé dans TTY_READ.
l'adresse de TTY_WRITE dans l'espace d'adressage
- L'adresse de TTY_WRITE du **TTY0** est bien 0x D020 0000.
- **q7**:
### A2. Programmation assembleur
- Q1:Réécrivez le code de la question précédente en utilisant la et li
```assembly
la $4, __tty_regs_map
li $5, 'x'
sb $5, 0($4)
```
- Q2:j label et jr $r permettent-elles d'effectuer un saut à n'importe quelle adresse?
- Q3:le code créant la section ".mytext" et suivi de l'addition des registres $5 et $6 dans $4
```assembly
.section .mytext,"ax"
addu $4,$5,$6
```
- Q4: À quoi sert la directive **.globl label ?**
### A3. Programmation en C
- Q1:les usages du mot clé static en C
- Il permet de réduire la visibilité de l'élément au bloc dans lequel il est défini
- Une variable statique à l'intérieur d'une fonction conserve sa valeur entre les invocations
- Q2:Déclarer des fonctions ou des variables externes
- Extern est utilisé pour déclarer une variable globale ou une fonction dans un autre fichier
- Le compilateur n'alloue pas de mémoire pour la variable lorsqu'il voit l'extern
- Q3:Déclarer un tableau de structures en variable globale
```c
struct test_s {
int a;
int b;
};
struct test_s tab[2];
```
- Q4:Quelle est la différence entre #include "file.h" et #include <file.h> ?
- **#include "file.**
Le préprocesseur recherche dans le même répertoire que le fichier contenant la directive.
- **#include <file.h>**
Le préprocesseur recherche de manière dépendante de l'implémentation,
il recherche des répertoires pré-désignés par le compilateur.
- Q6:n'incluant pas plusieurs fois le même ficher **.h**
- On peut définir une macro instruction différente au début de chaque fichier **.h**
```c
#ifndef NOM_DU_FICHIER_H
#define NOM_DU_FICHIER_H
/* contenu du fichier .h */
#endif /* NOM_DU_FICHIER_H */
```
- Q8:le mot clé volatile
### A4. Compilation
- Q1:Complétez les lignes de déclaration des variables pour la région kdata_region
-
- Q4: la différence entre = , ?= et +=
- = Réglage normal d'une variable
- =? Définition d'une variable uniquement si elle n'a pas de valeur
- += La valeur est ajoutée à la valeur actuelle
- Q6: Si on exécute **make** sans cible
- Q7: @ et - au début de commandes
- @ : Empêche l'affichage de la commande.
- : Désactive la vérification des erreurs pour la commande.
### A5
- Les 2 modes d'exécution de MIPS
- mode kernel: utilisé par le noyau
- mode user: utilisé par l'utilisateur
- l'espace d'adressage du MIPS
- l'ensemble des adresses que peut produire le MIPS
une adresse X est mappée en mémoire
- s'il y a une case mémoire pour cette adresse.
une adresse X mappée en mémoire est toujours accessible?
- si X< 0x80000000 elle est bien accessible n'importe quel mode.
mais si X>= 0x80000000 alors X n'est accessible que si le MIPS est en mode kernel
- registres système sont numérotés?
- Les registres système sont numérotés de 0 à 31.
donner les nom, les numéros et les rôles des registres.
- | cr_sr | $12 | le mode d'exécution du MIPS et le bit d'autorisation des interruptions |
| --------- | ---- | ------------------------------------------------------------ |
| cr_cause | $13 | la cause d'appel du noyau |
| cr_epc | $14 | l'adresse de l'instruction ayant provoqué l'appel du noyau<br />l'adresse de l'instruction suivante |
| cr_bar | $8 | l'adresse mal formée<br />si la cause est une exception due à un accès non aligné |
| cr_count | $9 | le nombre de cycles depuis le démarrage du MIPS |
| cr_procid | $15 | le numéro du processeur |
Peut-on faire des calculs avec des registres?
- non
les instructions qui permettent de les manipuler
- mtc0 et mfc0
- le contenu du registre status et le rôle des bits de l'octet 0
| 0 | IE | Interrupt Enable | 0 → interruptions masquées<br />1 → interruptions autorisées si ERL et EXL sont tous les deux à 0 |
| ---- | ---- | ---------------- | ------------------------------------------------------------ |
| 1 | EXL | EXception Level | 1 → MIPS en mode exception à l'entrée dans le kernel |
| 2 | ERL | ERror Level | 1 → au démarrage du MIPS <br />et certaines erreurs de la mémoire le MIPS est en mode kernel, <br />interruptions masquées |
| 4 | UM | User Mode | 0 → MIPS en mode kernel<br/> 1 → MIPS en mode user si ERL et EXL sont tous les deux à 0 |
- à quel endroit est stockée Le registre cause
- Le champ XCODE
donnez la signification des codes 0, 4 et 8
- | 0 | 0000b | interruption | un contrôleur de périphérique à lever un signal IRQ |
| ---- | ----- | ------------ | --------------------------------------------------- |
| 4 | 0100b | ADEL | lecture non-alignée |
| 8 | 1000b | syscall | exécution de l'instruction syscall |
- Pour quoi EPC contient l'adresse de l'instruction fautive.
- Il est important que le gestionnaire d'exception sache qu'elle est l'instruction fautive.
Le gestionnaire pourra lire l'instruction et éventuellement corriger le problème.
- 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 pour connaître l'adresse de retour.
- 3 instructions utilisables **seulement** lorsque le MIPS est en mode kernel
- | mtc0 \$GPR, $C0 | Move To Coprocessor 0 | \$GPR → COPRO_0( $C0 ) |
| --------------- | ----------------------- | ------------------------ |
| mfc0 \$GPR, $C0 | Move From Coprocessor 0 | \$GPR ← COPRO_0( $C0 ) |
| eret | Expection RETurn | PC ← EPC ; c0_sr.EXL ← 0 |
l'instruction syscall peut-être utilisée en mode user?
- oui
- l'adresse d'entrée dans le noyau?
- C'est 0x80000180 .
- le MIPS entre dans le noyau, après l'exécution de l'instruction syscall
- L'instruction syscall induit beaucoup d'opérations élémentaires dans le MIPS:
- EPC ← PC (adresse de l'instruction syscall )
- c0_SR.EXL ← 1 (ainsi les bits c0_SR.UM et c0_SR.IE ne sont plus utilisés)
- c0_cause.XCODE ← 8
- PC ← 0x80000180
- Quelle instruction utilise-t-on pour sortir du noyau
- l'instruction eret permet de sortir du noyau.
- PC ← EPC
- c0_SR.EXL ← 0 (ainsi les bits c0_SR.UM et c0_SR.IE sont à nouveau utilisés)
## Expériences réalisées
### Titre de l'expérience
### B1 Saut dans la fonction kinit()
- Q1
- éventuellement les sous-étapes 1
- une sous étape 2
- etc
- Q2
- Q3:l'adresse du démarrage du MIPS
- Boot_origin:0xbfc00000.
- Q4:
- Q5:
- Q6:
- Q7:
- Q8:
- Q9:l'adresse du sortie du contrôleur dans TTY
- L'adresse (aussi pour TTY_WRITE) est _tty_regs_map =0xd0200000.
- Q10:quand faut il initialiser le pile
- Ici, c'est initialisation de kinit (on initialiser le pointeur)
```assembly
la $29 _kdata_end
```
_kdata_end = _kdata_origin + _kdata_length
(0x80020000+ox00200000= 0x80040000)
- Q11:l'utilisation de **volatile**
- c'est a dire: la donnée de _tty_regs_map est pour **load/store** seulement. Et on ne peut pas utiliser un autre registre pour l'optimaliser.
#### Exercise
-
- l'explication pour label0.s
- C'est un résumé pour ce qu'il fait dans le fichier trace0.s
```assembly
K 12: <boot> ------------------------------------------------------- hcpua.S
K 12: 0xbfc00000 0x3c1d8040 lui sp,0x8040
K 13: 0xbfc00004 0x27bd0000 addiu sp,sp,0
K 14: 0xbfc00008 0x3c1a8000 lui k0,0x8000
K 15: 0xbfc0000c 0x275a0000 addiu k0,k0,0
K 26: 0xbfc00010 0x03400008 jr k0
K 27: 0xbfc00014 0x00000000 nop
K 37: <kinit> ------------------------------------------------------ kinit.c
K 37: 0x80000000 0x3c028002 lui v0,0x8002
K 38: 0x80000004 0x80430000 lb v1,0(v0)
K 39: 0x80000008 0x10600008 beqz v1,8000002c <kinit+0x2c>
K 48: --> READ MEMORY @ 0x80020000 BE=---1 --> 0x6c6c6548
```
```c
//for exercise seconde méssage
char seconde[] = "This is the second message!\n";
void kinit (void)
{
char *s,*ns;
for (s = hello; *s; s++) { // for all char in hello string
__tty_regs_map = *s; // write it to the tty output register
}
for (ns = seconde; *ns; ns++) { // for all char in hello string
__tty_regs_map = *ns; // write it to the tty output register
}
while (1); // infinite loop at the end
}
```
### B2: Premier petite pilote
- Q1: pourquoi on met la structure dans le fichier .c pas dans .h
- parce que pour le kernel, on a besion de savoir comment lire et écrire et c'est tout. Il y a moins de risque et il peut s'adapter a une autre structure.
- Q2: Pourquoi mis la fonction de ".globl clock" dans hcpua.s
- Parce qu'elle utilise les instructions particulières "mfc0"( qui est instruction protégée, move from co-processor).
Pourquoi utilise ".globl"
- Pour que les autres fichier .c peuvent le lire
- Q3: on observe que kinit n'est plus au début. C'est maintenant clock.
- Mais on peut voir depuis le fichier hcpua:
on peut utiliser l'instruction la pour obtenir l'adresse de kinit.
```assembly
la $26, kinit
```
-
#### Exercise
```c
//for exercise
char ask2[] = "Entrez le mot pour transformer en majuscule : ";
char name2[] = { [0 ... 63] = 'x' };
void Capitalize(void){
//FOR TEST
//char test[]={ [0 ... 5] = 'a' };
tty_puts (0, ask2);
tty_gets (0, name2, sizeof(name2));
if(name2[0]<='z'&&name2[0]>='a'){
//tty_puts (0, test);
name2[0]-=32;
}
tty_puts (0, name2);
}
```
### B3: Ajout d'une biblio
#### Exercise
- hcpua.s
```c
.globl cpuid
cpuid:
mfc0 $2, $15
andi $2, $2, 0xFFF
jr $31
```
- hcpu.h
```c
/**
* \brief cpu identifier
* \return a number
*/
extern unsigned cpuid (void);
```
- kinit.c
```c
//pour exercice
kprintf ("cpuid= [%d] \n", cpuid());
```