[SOS] pb IT !!!!!

David Decotigny david.decotigny at free.fr
Thu Jul 1 14:29:24 CEST 2004


Bonjour,

J'avoue ne pas bien comprendre a quoi correspond tout ce que tu nous 
envoie, et ou est SOS la-dedans. Je n'ai pas regarde dans le detail. 
N'empêche, le problème ne vient pas de SOS au niveau de l'IDT.

Il est certain que si tu rajoutes dans l'idt directement l'adresse de la 
fonction C a appeler, il va y avoir problemes des que le handler se 
terminera (return, ou fin de fonction). Il faut en effet qu'un handler 
d'interruption se termine par un appel a l'instruction 'iret', ou 
s'occupe de l'emuler par la recuperation du registre 'eflags' empile par 
le processeur, en depilant si necessaire les choses qui auraient ete 
empilees entre-temps. Si tu mets l'iret n'importe ou dans la fonction C 
appelee en tant qu'ISR, la pile explose.

Le plus simple pour tout ca est d'utiliser une technique analogue a 
*_wrappers.S, mais pour les interruptions logicielles (sauvegarde 
minutieuse des registres, restitution de la pile en tenant compte du 
eflags empile, puis iret). On peut imaginer une seule primitive 
assembleur, qui appelle une seule fonction, plutot que X routines 
assembleur qui appellent X fonctions par l'intermediaire d'un tableau, 
comme on le fait pour les IRQs et les exceptions. On peut remarquer 
d'ailleurs qu'on a implante la gestion des IRQs et des exceptions au 
niveau de l'article 2, et pas les interruptions materielles, qui 
n'etaient sensees intervenir qu'a la toute fin (processus utiolisateur).

Ceci dit, pour la bonne bouche, voila une solution "CRADE" pour que ca 
marche sans avoir a compiler un fichier assembleur supplementaire. 
Idealement, le fichier assembleur devrait contenir l'equivalent de ce 
qu'il y a dans les *_wrappers.S.

Dans cet exemple CRADE, la partie assembleur ne sauvegarde rien et ne 
restitue rien a l'identique, elle fait simplement :
  the_wrapper:
    call the_syscall
    iret
Sauf qu'on choisit de mettre tout ça dans du code C sous forme d'un bout 
d'assembleur inline, histoire d'etre sûr que c'est vraiment CRADE. On 
est obliges de mettre cet assembleur inline dans une fonction, donc on 
va le mettre dans une fonction C qu'on appellera jamais directement : ce 
qui nous interesse c'est le symbole qui est defini dans l'assembleur 
inline, pas la fonction englobante. Voila, je vous avais prevenu : c'est 
CRADE.

Bref, voici le code dans la fonction sos_main() de sos/main.c pour 
declarer le handler de syscall :
    sos_idt_set_handler(0x42, ugly_wrapper, 0);
(le syscall est l'interruption 0x42).

Dans le meme fichier sos/main.c, mais avant le sos_main(), on ecrit le 
truc degeulasse suivant :
   extern void ugly_wrapper(void);
   void fake_wrapper()
  {
    asm volatile(".globl ugly_wrapper ; ugly_wrapper: call the_syscall ; 
iret");
  }
Ca, ca fait ce que j'ai dit tout a l'heure avec l'assembleur inline. 
Remarquez que je n'ai pas mis de "static" devant fake_wrapper(), sinon 
gcc optimise trop et ne genere pas l'assembleur inline.

Bon, ensuite, il suffit de definir une fonction "the_syscall", une 
fonction C normale qui fait ce qu'on veut, par exemple :
  void the_syscall()
  {
    sos_bochs_printf("Syscall\n");
  }
(idem : remarquez l'absence de "static")

Et voila, pour voir que ca marche bien, il suffit de rajouter un :
    asm volatile("int $0x42;");
quelque part apres avoir fait le sos_idt_set_handler() indiqué plus haut.

Notons que c'est une solution CRADE de chez CRADE : aucun registre n'est 
sauvegardé avant l'appel au syscall. La solution propre serait de 
reprendre texto ce qu'il y a dans les *_wrappers.S et de mettre tout ca 
dans un syscall_wrapper.S par exemple. J'insiste : c'est ce qu'on 
appelle "quick and dirty". Surtout "dirty".

Bonne journee,

-- 
David Decotigny -- http://david.decotigny.free.fr



More information about the Sos mailing list