Anatomie d'un bug
By Samuel D. - 14/12/2004
Sommaire:

 

Bug : Explication Technique

 

Nous avons donc alerté rapidement Intel de ce comportement "étrange" en espérant obtenir une réponse. Il s'est ainsi avéré qu'Intel, qui semble ne pas avoir oublié le bug de division (!) du Pentium 60, a pris le problème relativement au sérieux. Ayant pu reproduire le bug rapidement, des ingénieurs d'Intel se sont rapidement penché sur la question et on pu trouver une explication logique à ce bug. Voyons donc le code qui met en évidence le bug :

 

 

Comme on le voit, ce code ASM peut être réparé en deux. Le premier calcule le FSB dans la variable "fsb". Comme on le voit, tout ce code est exécuté dans l'ALU puisque les divisions sont ici des divisions entières. Les instructions exécutées par l'ALU sont en bleu et par la FPU, en vert. On voit ainsi que le calcul de dramclock nécessite de passer de l'unité alu à l'unité FPU. Logique puisque "coef" est une valeur flottante. Pour ce faire, les deux opérandes de la multiplication flottante sont pushée dans la stack FPU en première et deuxième position par les instructions FILD (Fpu Integer LoaD) et FST (Fpu STore). Ensuite, la multiplication est effectuée entre les deux valeurs de la stack FPU st(0) et st(1). Le call final appèle la sous-routine "print_fsb_info" d'affichage des valeurs.

Ainsi, après avoir vérifié ce code sans y trouver d'erreur, les ingénieurs d'Intel ont ainsi tracé l'exécution du programme et étudié la valeur des registres en cours d'exécution. Il s'avère que, contrairement à ce que l'on pouvait croire, ce n'est pas la partie entière qui est en cause, mais la partie flottante. On constate ainsi que la multiplication flottante renvoie 0 pour la simple et bonne raison que la stack FPU ne renvoie pas de valeur st(0) ni st(1) ! Il semble donc maintenant que le bug provienne de la fonction chargées de remplir la stack FPU, FILD.

 

 

Cette instruction devrait donc mettre la valeur calculée précédemment dans la stack FPU sans problème. Or, ce n'est pas le cas. A vrai dire, cette instruction est la première à utiliser la stack FPU et, lorsqu'on vérifie l'état de la stack FPU, on s'apercoit que celle-ci est pleine, ce qui empeche l'instruction FILD de rajouter une entrée dans la stack ! Sachant que memtest86+ est lancé directement aprés le BIOS, on peut s'etonner que celui-ci passe le controle à l'OS avec une stack FPU pleine et pire, avec des exceptions FPU masquées, ce qui empeche l'affichage d'une erreur et retourne donc zèro. Le bug proviendrait donc du BIOS qui ne passe pas correctement le controle à l'OS. Pour vérifier ceci, Intel nous a fournis un bout de code ASM qui permet d'afficher le FPU Tag Word, qui indique justement l'état de la stack FPU.

 

 

Comme on le voit, deux bits par registres indiquent leur état actuels. Nous avons lancé l'exécutable immédiatement à l'invite du DOS d'ou nous lançons la version .exe de memtest86+ (qui montre aussi le bug, preuve que MS-DOS ne réinitialise pas la FPU au boot). Voici les résultats sur une DFI 855 et sur une MSI 875 :

 

DFI 855 FPU Tag Word @ BOOT

MSI 875 FPU Tag Word @ BOOT

 

Sur ces deux cartes (et sur l'immense majorité des cartes mères), le BIOS remplis correctement son rôle d'initialisation et renvoie les 16 bits à 1 (FFFF), ce qui signifie que les 8 registres FPU sont libre (Empty). Or, dans le cas des cartes Asus i915/925, le résultat renvoyé n'est pas le même :

 

Asus 915/925X FPU Tag Word @ Boot

 

0x5559h = 01.01.01.01.01.01.10.01b. Nous avons donc tous les registres contenant une valeur, la stack FPU est bien full.

Bien qu'il nous soit impossible de savoir pourquoi le BIOS passe le contrôle à l'OS avec une stack FPU pleine et les exceptions masquées (ce qui fait qu'au lieu de générer une erreur, la stack renvoie simplement 0) sur les cartes Asus i915/925, on peut clairement penser à une erreur de programmation du BIOS ou même un bug dans le code source générique d'AMi, les autres cartes utilisant un BIOS Award.

 

 

Suite ( Solution de résolution du bug )

Fermer