---
# System prepended metadata

title: TP1 du boot au 1er prog user

---

# 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());
```






