[Kos-dev] Travaux sur le CPL3

Thomas Petazzoni kos-dev@enix.org
Sat, 14 Jul 2001 11:01:43 +0200


Bonjour a tous,

Tout d'abord une bonne nouvelle : j'ai reussi hier soir pour la premiere
fois, du multithreading melangeant thread CPL0 et thread CPL3. Et de
plus le thread CPL3 fait un syscall pour appeler une fonction du noyau
:)

Mais bon ne nous enflammons tout de suite, la facon dont c'est fait est
plutot... gore :(

Tout d'abord, pour qu'une page soit disponible en lecture en CPL3, son
PD et son PT doivent etre en mode utilisateur. Donc impossible
d'utiliser du code du noyau (mappe avec des PD et PT superviseur) pour
ce thread. Il a donc fallu trouver une combine pour mettre du code CPL3
quelque part.

La solution trouvee est carrement gore : j'ai une fonction user_thread
dans wolfgang/main.c, non executable en CPL3, car dans le mapping du
noyau. Eh ben je recopie joyeusement le code de cette fonction a
l'adresse CPL3_CODE_ADDR (definie dans system.h). Comme je ne connais
pas la taille de la fonction, je recopie une page, ca suffit pour les
tests. Cette copie est faite par :

memcpy((char *)CPL3_CODE_ADDR, 
	 (char *) user_thread, PAGE_SIZE);

Ouf, on a du code dispo quelque part, et accessible en CPL3. Pas mal
pour un debut. Ensuite deuxieme probleme : il faut une pile en CPL3.
J'ai donc definit deux constantes dans system.h :

#define CPL3_HEAP_ADDR (2UL*1024*1024*1024+512*1024*1024) /* 2.5 G */
#define CPL3_HEAP_SIZE (512*1024*1024)                  /* 512 M */

CPL3_HEAP_ADDR definit le debut du tas (la ou seront alloues les pages
par l'appel sbrk() ). La fin du tas sert pour la pile. J'ai donc modifie
le code de map_virtual_to_physical pour qu'on puisse vraiment mapper une
page User en mode R/W. Ce qui n'etait pas possible jusqu'a maintenant.

Autre truc crade : pour pouvoir faire des outb depuis le thread en CPL3,
j'ai du modifie le IOPL (dans EFLAGS) pour le mettre a 3. Normalement
faudrait modifier la IO Map du TSS systeme pour donner les droits que
sur certains ports, mais pour les tests...

Autre truc pas crade : j'ai change le RPL (ou DPL je sais plus, enfin
bref le numero de privilege a partir duquel on peut appeler) de
l'interrupt gate du syscall, pour qu'on puisse effectivement faire int
$48 depuis le CPL3. 

Truc crade : j'ai modifie le code du syscall (bsyscall/_bsyscall.c) pour
que si on recoit EAX=1,EBX=2,ECX=3,EDX=4 ca affiche un joli message. En
effet pour les tests, je voulais pas passer par Babel, parce que je
voyais pas comment recuperer default_babel et tout ca.

Truc crade : la fonction user_thread peut presque rien faire, meme pas
utiliser de chaines de caracteres. Celles-ci seraient stockees dans la
section .data, et donc relogees de maniere absolue. Le thread irait donc
les chercher dans la zone du noyau, et on aurait le droit a un general
protection fault. Bref ce thread de test ne peut servir qu'a du test.

Autre chose : le thread user, quand il repasse en CPL0 (syscall ou IRQ),
il trouve son adresse de pile CPL0 dans le TSS systeme, c'est pourquoi
la fonction algo_reschedule met a jour ce TSS systeme.

Seul ombre au tableau : un truc bizarre. J'affiche un U en arrivant dans
le thread user, ensuite je fais un syscall. Puis je reviens du syscall
(d'apres msg de debug bochs), mais systematiquement j'ai une IRQ0 juste
derriere (avant meme d'afficher le S). Meme en 50Hz. Alors je comprends
pas bien pourquoi.

Conclusion de ces experiences : un premier apercu de ce que peut etre le
CPL3 et un syscall, mais beaucoup de choses reste a faire : la gestion
de plusieurs espaces d'adressage, la synchronisation des PDs du noyau,
le fork() ou equivalent...

Voila voila,

thomas
-- 
PETAZZONI Thomas
thomas.petazzoni@meridon.com     UIN : 34937744
Projet KOS : http://kos.enix.org
Page Perso : http://www.enix.org/~thomas/