• Aucun résultat trouvé

Chapitre II : Présentation de la méthode IDSM

II.2. Prise en compte des caractéristiques du processeur vérifié

II.2.3. IDSM et le pipeline

Pour un générateur de signature externe au processeur, les instructions à compacter ne peuvent être enregistrées qu’au moment de leur lecture en mémoire. Cependant, il existe des cas où une instruction est lue par le processeur sans qu’elle ne soit complètement exécutée. Ces cas sont fréquents avec une architecture pipeline, et encore plus avec une architecture utilisant une exécution spéculative lors des branchements. Il faut donc pouvoir gérer la signature en synchronisant précisément le comportement du watchdog et celui du pipeline du processeur, qui n'est pourtant pas directement visible.

Un premier problème de synchronisation se pose avec les aléas dus aux dépendances de données, qui peuvent conduire à des arrêts temporaires de la progression de certaines instructions dans les pipelines (« pipeline stall »). En l'absence d'exception, ces arrêts temporaires peuvent toutefois ne pas avoir de conséquence réelle sur la vérification de signature.

Les principaux problèmes pour la signature en présence d’un pipeline sont surtout liés à l’exécution d’un saut conditionnel ; ces complications sont appelées « aléas de contrôle ». Le drapeau qui permet au séquenceur de déterminer si un saut doit être pris ou non n’est en général généré que lorsque l’instruction précédente est dans l’étage d’exécution. L’étage de décodage de l’instruction de branchement n’est pas en mesure de calculer l’adresse de l’instruction suivante tant que la valeur du drapeau n'est pas calculée. Il faut alors retarder la décision sur le branchement, ou prendre une décision immédiate qui n'est pas forcément la bonne, sauf s'il est possible d'anticiper l'évaluation de la condition. Dans le contexte de vérification du flot de contrôle, certains cas d’aléas de contrôle peuvent conduire le dispositif de génération de signature à compacter des instructions qui ne seront pas exécutées par la suite, et bien évidemment ceci va poser des problèmes de cohérence pour la vérification.

Le cas particulier des prédictions de branchement sera traité plus en détail dans le paragraphe suivant ; nous allons nous attacher ici à la problématique générale et à une solution qui doit être la plus générale possible, vu que le comportement du processeur face aux aléas de contrôle est différent d’une architecture à une autre. Il existe quatre approches différentes de gestion des branchements : le « pipeline stall », l’anticipation des conditions de branchement, la prédiction ou encore le « branch delay slot ».

1. La première approche, appelée « pipeline stall », consiste à bloquer le pipeline le temps que l’instruction qui détermine le drapeau soit entièrement exécutée.

Figure 2-6 : Pipeline stall

Ö Cette approche ne pose aucun problème pour la génération des signatures, puisque

toutes les instructions chargées seront forcément exécutées.

Notons qu'intuitivement, le blocage du pipeline peut apparaître comme une solution assez intéressante pour empêcher les problèmes de cohérence des signatures. En effet, il suffirait de provoquer systématiquement un blocage pendant l’exécution des singularités pour que toutes les instructions qui vont être chargées soient exécutées. Cette solution ne peut malheureusement pas être utilisée, car selon l’architecture du processeur vérifié, un blocage peut être imposé globalement à tous les étages du processeur et par conséquent ne servirait à rien. De plus, chaque blocage induit une diminution des performances.

2. La deuxième approche pour gérer les problèmes de branchement est fournie par le

compilateur. Ce dernier peut dans certains cas anticiper l’instruction qui génère le drapeau ; le même genre d'approche est aussi utilisé de manière dynamique dans certains processeurs. Si le bon nombre d’instructions (défini par l’architecture) est intercalé entre la génération du drapeau et le saut, celui-ci peut s’effectuer sans délai. Il faut toutefois remarquer que cette anticipation est souvent impossible et qu’elle est très spécifique à une architecture donnée.

Ö Comme avec un blocage, aucun problème ne se pose dans ce cas pour la génération

des signatures car toutes les instructions chargées seront forcément exécutées.

3. Une troisième approche est l’exécution spéculative après prédiction de branchement : le processeur peut essayer de deviner si le branchement sera pris ou pas et commencer à exécuter les instructions correspondant à cette décision. Si le choix se révèle correct, la pénalité de branchement est éliminée alors que si le choix se révèle incorrect, il faudra vider une partie du pipeline et charger l’instruction correcte. Ceci doit bien sûr être géré de manière cohérente au niveau de la génération de la signature à vérifier par le watchdog.

4. La dernière approche, appelée branchement retardé ou « branch delay slot », est utilisée

dans de nombreux processeurs. Elle consiste à insérer, pendant la compilation, des instructions directement après le branchement.

Selon la politique utilisée, le retardement peut être sans optimisation avec l’insertion de NOP, ou avec optimisation avec l’insertion d’instructions utiles, et dans ce cas, 3 techniques sont possibles :

a. Déplacer une instruction précédente, fonctionnellement indépendante des autres

instructions et du calcul de la condition de branchement.

b. Dupliquer l’instruction de l’adresse de branchement.

c. Laisser l’instruction suivante.

Face à cette panoplie d’approches de gestion des branchements, la solution proposée de manière à respecter au maximum la généralité de la méthode sera identique à la technique utilisée dans WDP. Le principe de cette solution consiste à ne traiter qu’un nœud à la fois :

Pour les nœuds de destination, le fonctionnement du watchdog n’est pas modifié,

ceux-ci étant toujours traités au moment de leur chargement.

Pour les nœuds de séquencement, le traitement s’étale sur tout le temps pendant lequel

l’instruction de séquencement est présente dans le pipeline du processeur.

Pour cela, le watchdog calcule l’âge de l’instruction de séquencement (le nombre de lectures ayant eu lieu entre le début du chargement de cette instruction et l’exécution de celle-ci). En fonction de l’âge, le watchdog saura si le branchement a été effectué ou pas ou s’il y a eu un branchement inopiné. Cette solution implique que le watchdog traite les singularités non plus au moment de leur chargement par le processeur mais à retardement, donc en fonction de leur âge.

Cette solution nécessite également que le watchdog conserve toutes les signatures intermédiaires des instructions chargées par le processeur mais non encore exécutées.

Pipeline et interruptions :

La présence de pipeline complique le traitement des interruptions : lors du déclenchement d’une interruption non-masquable, la routine de traitement doit parfois être lancée immédiatement. Le pipeline contiendra alors des instructions partiellement exécutées.

La seule solution efficace est de vider partiellement le pipeline. Cette opération peut toutefois compliquer le redémarrage du programme après le traitement de l’interruption (par exemple, il faut retrouver l’adresse de la première instruction dont l’exécution n’a pas été achevée).

Figure 2-8 : Gestion des interruptions dans un pipeline

En cas de départ en exception sur une instruction de séquencement conditionnelle, le branchement peut avoir eu lieu sans que l’instruction destination ait été chargée. L’adresse du retour du processeur sera donc la destination du branchement et non pas celle située en séquence après la dernière unité chargée avant le départ.

Pour identifier ce cas gênant, lors du retour de l’exception, la solution la plus simple consiste à empiler l’âge du nœud en cours de traitement au moment du départ. De cette manière, le traitement du nœud interrompu peut reprendre normalement, en fonction de l’âge du nœud, lors du retour d’exception.