[Kos-dev] Double Fault
Christophe Avoinne
kos-dev@yoda.isnpro.com
Wed, 21 Mar 2001 17:45:52 -0800
Bien j'ai regardé dans la section "Instruction Set Reference" du manuel
Intel, volume 2 la description pour l'instruction IRET/IRETD :
Je peux lire :
"
In Protected Mode, the action of the IRET instruction depends on the
settings of the NT (nested
task) and VM flags in the EFLAGS register and the VM flag in the EFLAGS
image stored on
the current stack. Depending on the setting of these flags, the processor
performs the following
types of interrupt returns:
• Return from virtual-8086 mode.
• Return to virtual-8086 mode.
• Intra-privilege level return.
• Inter-privilege level return.
• Return from nested task (task switch).
"
On lit donc bien qu'il faut que ce soit le bit NT du registre EFLAGS qui
soit à 1 lorsqu'on exécute le IRETD pour faire le "task switch" et non le
bit NT de l'image sauvée de ce registre dans la pile.
Je crois que seul le code erreur est empilé dans la pile du double-fault. En
effet :
"
IF NT ?1
THEN GOTO TASK-RETURN;
FI;
"
puis
"
TASK-RETURN:
Read segment selector in link field of current TSS;
IF local/global bit is set to local OR index not within GDT limits
THEN #GP(TSS selector);
FI;
Access TSS for task specified in link field of current TSS;
IF TSS descriptor type is not TSS or if the TSS is marked not busy
THEN #GP(TSS selector);
FI;
IF TSS not present
THEN #NP(TSS selector);
FI;
SWITCH-TASKS (without nesting) to TSS specified in link field of current
TSS;
Mark the task just abandoned as NOT BUSY;
IF EIP is not within code segment limit
THEN #GP(0);
FI;
"
A aucun moment, on ne dépile un CS:EIP et EFLAGS depuis la pile du Double
Fault. C'est donc parce que ni un CALL, ni un INT, ni une exception n'empile
ces valeurs lors d'un TASK GATE.
Par contre je sais qu'un code error est empilé dans la pile Double Fault car
c'est spécifié dans le manuel Intel, volume 3.
Conclusion :
1)
- vérifier que le bit NT dans le registre EFLAGS quand on tourne dans le TSS
Double Fault est à 1;
- s'il ne l'est pas, le positionner dans le champ EFLAGS du TSS Double Fault
lors de son initialisation, comme ça, dès le premier Double Fault, ce bit
sera déjà positionné;
- si ce bit est remis à 0 lors d'un IRETD (en principe, non, compte tenu de
ce que je lis au-dessus, il ne le fait pas), ben faut envisager alors de
positionner ce bit à 1 avant le IRETD.
- avant de faire un iretd, ne pas oublier de dépiler le code erreur (c'est
au software de le faire et non au CPU!).
2)
-le CS:EIP et EFLAGS du code fautif est dans le TSS système.
-le CS:EIP et EFLAGS du code à exécuter pour le Double Fault est dans le TSS
Double Fault. C'est là qu'il faudrait positionner une fois pour tout le bit
NT dans le champ EFLAGS (en espérant qu'il n'est pas remis à 0 par le "task
switch").
Voilà, ce devrait être plus clair maintenant.