---
# System prepended metadata

title: SMC Compte Rendu TP8

---

# SMC Compte Rendu TP8

## Binôme 
* Guillaume VACHERIAS : 21204391
* Yann QUERIC : 28712032

## Questions sur le preloader

### Question 1
*À quoi sert un preloader ?*

Un Preloader permet de charger en RAM le code du Bootloader correspondant à l’OS qu’on veut. Le Preloader est spécifique pour l’architecture du système et indépendant du système d’exploitation.

### Question 2
* *Où se trouve stocké le code du preloader au démarrage de la plateforme TSAR?*
Le preloader est stocké dans la ROM de boot extern qui est accessible par un IO_bridge du cluster 0 pour l'architecture **TSAR_IOB**. Dans l'architecture **TSAR_LETI**, le preloader est stocké dans les 16000 premiers octets de l'espace d'adressage du cluster 0;

* *Comment les coeurs accèdent_ils au code du preloader ?*
Lors du démarrage la MMU n'est pas encore activé ainsi, tous les coeurs n'ont que accès aux adresses physique. De plus, les adresses des registres permettant les accès à distant des autres cluster est à 0 donc tous les coeurs n'ont qu'accès à l'adresse physique du cluster 0

### Question 3
*Comment fait-on pour qu'un code ne soit exécuté que par un seul core ?*

Les core sont mis en mode basse consommation (low-power state) qui est un état idle du core. Ces core en état idle seront réveillés par IPI (Inter Processor Interrupt).


### Question 4
*A quel moment les cores sortent-ils du preloader ?*

Les core sortent du preloader au moment où ils bloquent. Sauf pour le core 0 du cluster 0 qui va exécuter le code du bootloader. 


## Questions sur le bootloader

### Question 1 
* *À quoi sert le bootloader ?*
Le Bootloader est spécifique à la fois à l’architecture et à l’OS. En effet, il charge en mémoire le code de l’OS. Le Bootloader alloue à chaque cluster 6 zone mémoire de taille fixe : 

| Name        | Description                | Base physical address    |
| ----------- | -------------------------- | ------------------------ |
| PRE_LOADER  | pre-loader code            | PRELOADER_BASE (0)       |
| KERNEL_CODE | kernel code and data       | KERNEL_CODE_BASE (16 KB) |
| BOOT_CODE   | boot-loader code and data  | BOOT_CODE_BASE (2 MB)    |
| ARCH_INFO   | arch_info.bin file copy    | ARCH_INFO_BASE (3 MB)    |
| KERNEL_ELF  | kernel.elf file copy       | KERNEL_ELF_BASE (4 MB)   |
| BOOT_STACK  | boot stacks (one per core) | BOOT_STACK_BASE (6 MB)   |

* *Quels périphériques doit il pouvoir accéder ?*
Les périphériques qu'il doit pouvoir accéder sont : 
    * **TTY** pour l'affichage des messages log
    * **IOC** pour accéder au disque 

* *Quels formats de fichier doit-il pouvoir analyser ?*
Le format ELF pour l'exécutable du noyau.

### Question 2
*Dans quel(s) fichier(s) est rangée la description de la plateforme matérielle ?*

Dans le fichier *arch_info.bin*, on peut retrouver les caractéristiques de l'architecture matérielle notamment : 
* Nombre de clusters
* Nombre de coeurs dans chaque cluster
* Taille de la mémoire physique dans chaque cluster
* Nombre et types des périphériques

Ce fichier est généré par le script *arch_info.py*.


### Question 3
*Pourquoi le code du bootloader est-il recopié dans tous les clusters ?*

Le bootloader est recopié dans tous les clusters puisque chaque cluster doit pouvoir initialiser les 6 zones de mémoires PRE_LOADER, KERNEL_CODE, BOOT_CODE, ARCH_INFO, KERNEL_ELF, BOOT_STACK. En particulier, les zone BOOT_CORE, KERNEL_CODE ainsi que l'initalisation des registres sont fait en parallèle sur chaque cluster, ce qui nécessit le code du bootloader dans tous les cluster.

### Question 4 
* *Pourquoi chaque core, a-t-il besoin d'une pile ?*
Chaque core a besoin d'une pile pour pouvoir exécuter un thread. En effet, le bootload initialise le registre sp (stack pointer). Ainsi pour un thread quelconque, le thread descripteur contient un kernel stack pour permettre l'initialisation du stack pointer.

* *où sont-elles placées ?*
Le stack pointer est contenu dans le kernel stack.

### Question 5 
* *Qu'est-ce qu'une IPI ? Comment sont-elles utilisées par le bootloader ?*
Une IPI (Inter Processor Interrupt) permet d'envoyer des interruption sur un processor. On l'utilise à la 2e phase de l'exécution du bootloader pour réveiller les core qui sont en état idle (low power state). 

## Questions sur kernel_init

### Question 1 
*Comment dans chaque cluster, le noyau a-t-il accès à la description de la plate-forme matérielle ?*

Au bootloader, nous avons initialisé pour chaque cluster 6 zone de mémoire fixe dont ARCH_INFO à l'adresse physique base ARCH_INFO_BASE (3MB) qui contient la structure du fichier **arch_info.bin**. Ce dernier décrit les caractéristique du matérielle.

### Question 2 
*Comment almos_mkh identifie-t-il les coeurs de la plate-forme matérielle ?*

Chaque core est identifié par une valeur gid (global hardware identifier). Étant donné que les cores sont répartis dans plusieurs cluster, on utilise un identifiant cxy pour identifier les cluster et une valeur lid (local core index).  Ainsi la valeur gid est calculé par : $gid = (cxy << 2) +lid$. Cette association index [cxy, lid] au gid est défini dans le fichier arch_info.bin.

### Question 3

*Le kernel exécute sur chaque coeur la fonction kernel_init() qui initilalise le thread IDLE qui est le thread choisi par le scheduler d'un coeur quand tous les autres threads placés sur ce coeur sont bloqués.*

* *Où sont rangés les descripteurs de threads IDLE ?*
Les descripteurs de threads IDLE d'un cluster sont rangés dans le kernel **process_zero** du cluster correspondant.  En effet, kernel **process_zero** contient tout les running thread du cluster.

* *Combien y a-t-il de threads idle ?*
Il est nécessaire d'avoir un thread idle par cores. En effet, chaque core d'un cluster doivent pouvoir être mis dans l'état idle.


### Question 4 et 5
*Pour quelle raison la fonction kernel_init() utilise-t-elle des barrières de synchronisation ?*

*Pour quelle raison, utilise-t-on à la fois des barrières locales et des barrières globales ?*

On a 2 problème pouvant expliquer pourquoi on utilise des barrières : 
* Instanciation du kernel sur tous les clusters (écriture) par le core[0] du cluster[0]
* Création des tables de pages génériques et les listes des segments virtuelles sur tous les cluster par leurs processor[0] (écriture).

Ce sont des opérations d'écriture, ainsi une barrière de synchronisation est nécessaire pour ces 2 problèmes afin de gérer le problème de cohérence.

Imaginons que nous avons 2 processeurs qui exécutent la copie des instances en parallèle. Ceci pourra poser un problème de cohérence si les 2 processeurs copie l'instance au même cluster à un même moment. De même pour la création des pages de tables de chaque cluster.

### Question 6
*Dans le cas d'une barrière globale, expliquez précisément la valeur du premier argument passé à la fonction xbarrier_wait()*

Le premier argument passé dans la fonction est une structure définissant l'état de la barrière de chaque cluster. Elle permet de synchroniser les kernel threads en exécution sur les différents cluster. 

Voici la structure utilisé : 
```clike=
typedef struct xbarrier_s
{
	uint32_t current;       /*! number of arrived threads                     */
	uint32_t sense;         /*! barrier state (toggle)                        */
	uint32_t padding[(CONFIG_CACHE_LINE_SIZE>>2)-2];
}xbarrier_t;
```

* current : Indique le numéro de thread exécuté actuellement
* sense : état de la barrière. Si sense=1 barrière est activée sinon désactivée.

### Question 7
*Quel est le rôle de la fonction cluster_init() définie dans le fichier*

On retrouve 2 fonctions init dans le fichier *cluster.h* : 
* cluster_info_init : permet d'initialiser les variables globale et paramètres des clusters. 
* cluster_manager_init : permet d'initialiser 
    * paramètre des architecture hardware (local et global)
    * descripteur des cores et leurs scheduler
    * l'allocation mémoire de chaque cluster
    * DQDT, structure globale décrivant les ressources (core et mémoire) disponible de chaque cluster.

## Question aux prof
* *low power state* : ex réduction fréquence horloge