[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