[SOS] Pagination

stephane duverger duvergers at chello.fr
Ven 21 Oct 16:00:53 CEST 2005


Salut,

J'ai pas totalement suivi la conversation mais j'ai peut-etre une 
reponse a :

"j'ai pas l'impréssion qu'on est les outils pour faire du Multi-Segment"


A l'epoque j'ai voulu creer un os multisegmenté aussi. Je m'etais tourné 
vers le compilateur openWatcom (et son linker wlink) qui gere le 
multisegment grace a des far pointers (48 bits). Cependant le linker 
proposé n'etait pas aussi souple et puissant que "ld" quant a la 
generation de binaires ELF. L'idee aurait ete de compiler avec 
openWatcom et de linker avec "ld". Le probleme c que watcom ne sait 
pondre que des objets relocalisables au format "omf" et pas en ELF et 
"ld" attend des objets ELF.

Plutot que de patcher le compilo (un peu hardcore) j'ai pensé modifier 
le linker pour le transformer en un espece de omf2elf au niveau des 
objets relocasilables. Dans le code du linker il y a tout ce qu'il faut 
pour gerer l'elf et c assez simple a comprendre. De plus les 
developpeurs (michal en particulier) sont assez sympa.

Peut-etre qu'un tel outil existe deja. En tout cas ce compilateur gere 
les segments et pourrait repondre a tes attentes. Je te parle de ca mais 
c'etait il y a un an. Peut-etre qu'aujourd'hui le linker sait generer de 
simples objets relocalisables.

Voici quelques liens : attention le support de lunix est actif 
uniquement dans leur version de developpement. Il faut donc recompiler 
le compilateur a partir des sources recuperees via perforce. Mais tout 
est expliqué en ligne.

http://downloads.openwatcom.org/ftp/source/
http://www.openwatcom.org/support/reference_content.html

bonne continuation.

++stf

PS: Sinon l'idée de comprendre la pagination et de l'utiliser dans ton 
OS est vraiment bonne aussi :). Tu decouvriras des choses vachement 
interessantes qui ont ete presentées dans les articles sur SOS notamment 
le mirroring du repertoire de pages qui est une technique vraiment 
fabuleuse. Enfin moi je suis resté sur le cul tellement c simple a 
mettre en oeuvre et ingenieux.

KAISER Edouard wrote:

>Salut à tous !
>Bon bah il faut bien s'y résoudre, j'ai pas l'impréssion qu'on est les
>outils pour faire du Multi-Segment, alors plutot que faire de la
>bidouille avec la segmentation et bien je me met à la pagination,
>comme tout le monde :D
>Comme l'indique les tutoriaux de SOS il faut être sur qu'avant
>d'activer le bit 31 de CR0 le Repertoire des tables et les tables sont
>valides sinon ça va donner n'importe quoi.
>Pour ne pas prendre des risques, j'ai donc fait pareil : De L'identity
>mapping des 8 premiers Mo de la mémoire vive, ce qui est amplement
>suffisant pour l'instant, c'est surtout histoire de tester...
>Plutôt que de faire un bête copier-coller des fonctions SOS j'ai
>souhaité implémenter moi même ma fonction d'Identity mapping.
>J'en suis arrivé à un stade ou je pensais que c'était ok, et bien non
>impossible de me dépatouiller de de CPULOOP(1) dans bochs, que nous
>avons du tous avoir.
>Cela se passe bien sur au moment d'activer le bit 31 de CR0.
>Je pourrais vous filer un tarball mais je doute que quelqun aura le
>courage et le temps de s'y pencher, alors je préfère vous filer mes
>deux fonctions qui se battent en duel, peut etre que quelque chose m'a
>échappé et qui sera flagrant pour un autre ! :D
>
>/* Structure d'une entree dans le "Repertoire des tables des pages" */
>struct x86_page_directory_entry
>{
>	u8 Present0 : 1;
>	u8 Read_Write1 : 1;
>	u8 User_Supervisor2 : 1;
>	u8 Write_Through3 : 1;
>	u8 Cache_Disabled4 : 1;
>	u8 Accessed5 : 1;
>	u8 Reserved6 : 1;
>	u8 PageSize7 : 1;
>	u8 GlobalPage8 : 1;
>	u8 Avail9_11 : 3;
>	u32 PageTable_Address : 20;
>} __attribute__ ((packed));
>
>/* Structure d'une entree dans la "Table des pages" */
>struct x86_page_table_entry
>{
>	u8 Present0 : 1;		
>	u8 Read_Write1 : 1;
>	u8 User_Supervisor2 : 1;
>	u8 Write_Through3 : 1;
>	u8 Cache_Disabled4 : 1;
>	u8 Accessed5 : 1;
>	u8 Dirty6 : 1;
>	u8 Attribute_Index7 : 1;
>	u8 GlobalPage8 : 1;
>	u8 Avail9_11 : 3;
>	u32 Page_Address : 20;
>} __attribute__ ((packed));
>
>static struct x86_page_directory_entry* Page_Directory;
>static struct x86_page_table_entry* Page_Table_1;
>static struct x86_page_table_entry* Page_Table_2;
>
>/* Initialisation de la pagination */
>errno init_paging(void)
>{
>	int i;
>	unsigned int Page_Table_Address;
>	struct x86_page_table_entry* Address_Table;
>			
>	Page_Directory = (struct x86_page_directory_entry*)(0x0);
>	Page_Table_1 = (struct x86_page_table_entry*)(0x1000);
>	Page_Table_2 = (struct x86_page_table_entry*)(0x2000);
>	
>	/* Page Direcory 1 */
>	Page_Directory->Present0 = 1;
>	Page_Directory->Read_Write1 = 0;
>	Page_Directory->User_Supervisor2 = 0;
>	Page_Directory->Write_Through3 = 0;
>	Page_Directory->Cache_Disabled4 = 1;
>	Page_Directory->Accessed5 = 0;
>	Page_Directory->Reserved6 = 0;
>	Page_Directory->PageSize7 = 0;
>	Page_Directory->GlobalPage8 = 0;
>        /* 20 bits de poid fort */
>        Page_Table_Address = (unsigned int)Page_Table_1;
>        Page_Table_Address = Page_Table_Address & 0xfffff000;
>	Page_Table_Address = Page_Table_Address >> 12;
>        /*----------------------*/
>	Page_Directory->PageTable_Address = Page_Table_Address;
>	
>	/* Page Directory 2 */
>	(Page_Directory+1)->Present0 = 1;
>	(Page_Directory+1)->Read_Write1 = 0;
>	(Page_Directory+1)->User_Supervisor2 = 0;
>	(Page_Directory+1)->Write_Through3 = 0;
>	(Page_Directory+1)->Cache_Disabled4 = 1;
>	(Page_Directory+1)->Accessed5 = 0;
>	(Page_Directory+1)->Reserved6 = 0;
>	(Page_Directory+1)->PageSize7 = 0;
>	(Page_Directory+1)->GlobalPage8 = 0;
>	/* 20 bits de poid fort */
>        Page_Table_Address = (unsigned int)Page_Table_2;
>        Page_Table_Address = Page_Table_Address & 0xfffff000;
>	Page_Table_Address = Page_Table_Address >> 12;
>        /*----------------------*/
>        (Page_Directory+1)->PageTable_Address = Page_Table_Address;
>
>	/* On mappe les 8 premiers megaoctets avec la pagination */	
>	for(i=0;i<2048;i++)
>		insert_identity_translation(i*0x1000);
>	
>    /* Activation de la pagination */
>    __asm__("xor %eax,%eax \n \
>                   movl %eax,%cr3 \n \
>                   movl %cr0,%eax \n \
>                   orl $0x80000000,%eax \n \
>                   movl %eax,%cr0");
>	
>	return OS_SUCCESS;
>}
>
>/* Permet d'associer une adresse lineaire "lAddr" a une adresse
>virtuelle "vAddr" */
>errno insert_identity_translation(lAddr Linear_Address)
>{
>	unsigned int PDE, PTE, Offset, Page;
>	struct x86_page_table_entry* Page_Table_Address;
>	
>	/* Informations decortiquees de l'adresse lineaire */
>	PDE = get_index_PDE(Linear_Address);
>	PTE = get_index_PTE(Linear_Address);
>	Page = PAGE_ALIGN_INF(Linear_Address);
>	Offset = Linear_Address - Page;
>	
>	/* On recupere l'adresse de la table des pages correspondantes */
>	Page_Table_Address = (struct
>x86_page_table_entry*)((Page_Directory+PDE)->PageTable_Address);
>	
>	/*
>	 * Initialisation des champs dans la table des pages selon l'index dans
>     * l'adresse lineaire.
>	 */
>	(Page_Table_Address+PTE)->Present0 = 1;
>	(Page_Table_Address+PTE)->Read_Write1 = 0;
>	(Page_Table_Address+PTE)->User_Supervisor2 = 0;
>	(Page_Table_Address+PTE)->Write_Through3 = 0;
>	(Page_Table_Address+PTE)->Cache_Disabled4 = 1;
>	(Page_Table_Address+PTE)->Accessed5 = 0;
>	(Page_Table_Address+PTE)->Dirty6 = 0;
>	(Page_Table_Address+PTE)->Attribute_Index7 = 0;
>	(Page_Table_Address+PTE)->GlobalPage8 = 0;
>	/*
>	 * !!! On depasse les 20 bits a partir de Linear_Address = 0x100000 !!!
>	 * Il faut donc seulement recuperer les 20bits de poid fort de l'adresse
>         * physique comme l'exige la norme Intel.	
>	 */
>	Page = Page & 0xfffff000;
>	Page = Page >> 12;
>	(Page_Table_Address+PTE)->Page_Address = Page;
>	/*-------------------------------------------------------------*/
>	
>	return OS_SUCCESS;
>}
>
>/* Recupere l'index dans le repertoire des pages a partir d'une
>adresse lineaire */
>u32 get_index_PDE(lAddr Linear_Address)
>{
>	return (Linear_Address >> 22);
>}
>
>/* Recupere l'index dans la table des pages a partir d'une adresse lineaire */
>u32 get_index_PTE(lAddr Linear_Address)
>{
>	unsigned int Temp;
>	
>	Temp = (Linear_Address >> 12);
>
>	Temp = Temp & 0x000003ff;	
>	
>	return Temp;
>}
>
>/* Recupere l'offset dans une page a partir d'une adresse lineaire */
>u16 get_offset(lAddr Linear_Address)
>{
>	return (Linear_Address & 0x00000fff);
>}
>
>
>Voila désolés de donner du code comme cela, si vraiment certain
>veulent un tarball, je le donnerai =)
>Merci !
>--
>KAISER Edouard.
>Wiki-Blog : http://kaiser.edouard.free.fr/
>BesOS : http://besos.mtp.epsi.fr/
>_______________________________________________
>Sos mailing list
>Sos at the-doors.enix.org
>http://the-doors.enix.org/cgi-bin/mailman/listinfo/sos
>
>  
>



Plus d'informations sur la liste de diffusion Sos