[SOS] Le gestionnaire de pages physiques
David
mykeysdavid at gmail.com
Mar 14 Aou 20:32:54 CEST 2007
Bonjour,
C'est mon premier message sur cette liste, qui semble une niche
d'information.
Merci pour SOS, qui me permet de comprendre certains principes des OS 32
bits, ce qui me permet d'améliorer mes compétences en C et ASM x86.
Mon but est de faire un OS graphique vers la fin (très simple), ce qui
signifie que je vais d'abord me rendre à la gestion des threads
utilisateurs et j'essaierai d'implémenter un simple contrôleur du mode
v8086. Avec ça, il me semble que je pourrai contrôler efficacement la
configuration du mode vidéo (obtention des paramètres, définition du
mode et accès à l'interface du mode protégé VBE) (le bootsecteur me
permet de faire ça, mais ce n'est pas très bon (aucun contrôle de
validité)).
Pour l'instant, j'arrive au gestionnaire de pages physiques, dont je
semble avoir compris le fonctionnement, et j'ai le code suivant (que
j'ai mis en pièce jointe). Mais, cela génère une boucle infinie sous
qemu, avec des valeurs totalement loufoques de "i" et "page_descr"
(fonction physmem_init() ).
Après quelques tests, je me rends compte de ceci (j'ai 32 Mb de RAM sous
qemu):
start (le début de la mémoire gérée) est à 4096 (correct);
end (la fin de la mémoire gérée) est à 33554432 (32 Mb exact) (correct);
Nombre de pages (end-start)>>PAGE_SHIFT est à 8191 (encore correct);
l'adresse de "i" sur la pile est 2 164 144;
DESCR_START (qui correspond à PALIGNS( & __e_kernel )) est à 2 097 152
(plus bas que i??) ??
Je ne comprends pas du tout ce qui se passe, pourquoi le symbole
__e_kernel est-il comme cela ? C'est la source de mes problèmes (car
dans ce cas page_descr pointera éventuellement vers i et l'écrasera, ce
qui crée une boucle infinie ...
Je compile avec cygwin et le cross-compilateur que vous avez fourni
(binutils 2.16, gcc 3.4.4) sous Windows. Le makefile est légèrement
modifié pour automatiquement utiliser l'image de grub fournie. Je mets
le zip en pièce jointe et, si ça marche pas (aucune expérience en
mailing-lists), allez sur
http://serveur1.archive-host.com/membres/up/1521434322/MyOS.zip .
>>Merci de m'aider.
P.S Voici certaines fonctions que je juge pratiques, sont-elles bien ?
Soft_Ramsize: Calcul en C de la taille de la RAM. Utile quand le
boot sector et grub ne fonctionne pas. Cette fonction doit être
appelée avant la pagination (car elle cherche à écrire directement
en mémoire). La taille minimale précisée est égale à 4 Mio - 4 o.
Cette fonction ne *devrait* pas effacer les données en RAM (elle
remet les données qu'elle écrase), mais je n'ai pas eu à voir si ça
le faisait vraiment.
C'est pour éviter d'écraser le noyau que je mets 4 Mo.
L'algorithme utilisé est simple (c'est le même principe qu'une
recherche binaire). "magic" vaut "01111111111111111111111111111111b"
(c'est un choix personnel). Ça boucle tant que l'espace entre deux
tests est plus petit qu'un octet.
void soft_ramsize(unsigned long *ramsize){
volatile unsigned long magic = 2147483647,tmp=0;
/* minRAM = 4MB (don't blow up the kernel code), maxRAM = 4GB .
Remove 4 bytes because it's a long (magic do 4 bytes in memory). */
unsigned long minRAM = 0x3FFFFC, maxRAM = 0xFFFFFFFC;
register unsigned long ramsz = (maxRAM - minRAM) >> 1;
volatile unsigned long *tptr;
do{
tptr = (long*)(ramsz);
tmp = *tptr;
*tptr = magic;
/* Higher! */
if (*tptr == magic){
*tptr = tmp;
tmp = ramsz;
minRAM = ramsz;
ramsz += (maxRAM - minRAM) >> 1;
}
/* Lower !*/
else{
tmp = ramsz;
maxRAM = ramsz;
ramsz -= (maxRAM - minRAM) >> 1;
}
} while (ramsz != tmp); /* While there is another comparison */
*ramsize = (ramsz + 4) >> 10;
}
Tvmem_putstring: affiche une chaîne rapidement à l'écran. Cette
fonction ne gère pas encore le dépassement (quand on dépasse 24,79).
Elle est écrite afin d'utiliser les fonctionnalités du processeur
(lodsb et stosw). On utilise une instruction pour écrire deux octets
dans la RAM vidéo (stosw), ce qui accélère le traitement. l'attribut
est dans ah et le caractère dans al (les processeurs intel sont
little endian).
/void tvmem_putstring(u8 row, u8 col, u8 a, const char* str){
/* Explanations:
movb %0,%ah > Sets the attribute into ah ONCE
1:
lodsb > Loads an char into AL from memory at ESI
orb %al,%al > Or'd ah and ah. This returns zero only if
AL is zero.
jz 2f: > If the or was zero, jump forward to 2: (end)
stosw > Write AX(AH and AL) into memory at EDI
jmp 1b > Jump backward at 1: (write char)
2:
*/
asm volatile("movb %0,%%ah\n1: lodsb; orb %%al,%%al; jz 2f;
stosw; jmp 1b\n2:"
:
: "m" (a), "D" (VIDEO + ((row * COLUMNS + col) << 1)), "S" (str)
: "memory", "ax"
);
}/
mov_blk: transfère des double mots (des blocs de 32 bits) de src à
dest. Un des exemples de
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html .
c'est de l'ASM inline. cela permet de copier 4 octets à la fois et
donc de pouvoir accélérer de 400% les traitements !
/#define mov_blk(src, dest, numwords) \
asm __volatile__ ("cld\n\t"\
"rep movsl"\
: \
: "S" (src), "D" (dest), "c" (numwords) \
)/
memcpy: version optimisée qui utilise mov_blk pour faire la majorité
du travail:
/void * memcpy(void* dest, const void* src, size_t size){
long dwsize = size >> 2;
char i;
char bsize = size & 3;
long rsize = size - bsize;
char* dest_r = dest + rsize;
char* src_r = (char*)(src + rsize);
mov_blk((long*)dest,(long*)src, dwsize);
for ( i = 0; i<rsize; i++ ) *dest_r++ = *src_r++;
return dest;
}/
-------------- section suivante --------------
Une pièce jointe HTML a été nettoyée...
URL: http://the-doors.enix.org/pipermail/sos/attachments/20070814/b7c77c77/attachment-0001.html
-------------- section suivante --------------
Un texte encapsulé et encodé dans un jeu de caractères inconnu a été nettoyé...
Nom : physmem.h
Url : http://the-doors.enix.org/pipermail/sos/attachments/20070814/b7c77c77/attachment-0002.txt
-------------- section suivante --------------
Un texte encapsulé et encodé dans un jeu de caractères inconnu a été nettoyé...
Nom : physmem.c
Url : http://the-doors.enix.org/pipermail/sos/attachments/20070814/b7c77c77/attachment-0003.txt
-------------- section suivante --------------
Une pièce jointe non texte a été nettoyée...
Nom: MyOS.zip
Type: application/octet-stream
Taille: 120973 octets
Desc: non disponible
Url: http://the-doors.enix.org/pipermail/sos/attachments/20070814/b7c77c77/attachment-0001.obj
Plus d'informations sur la liste de diffusion Sos