[SOS] Pagination

romain romain at hexanium.com
Sam 22 Oct 14:38:02 CEST 2005


Salut,

Je viens de lire ce message qui me concerne aussi indirectement, c'est
tres instructif, tres précis et vraiment sympa de passer du temps sur
les codes de ceux qui galere, je suis pas le principale intéraissé par
cette réponce mais j'ai envis de vous dire merci !

Formidable boulot !

A++

Romain


> -----Message d'origine-----
> De : sos-bounces at the-doors.enix.org 
> [mailto:sos-bounces at the-doors.enix.org] De la part de Thomas Petazzoni
> Envoyé : samedi 22 octobre 2005 14:17
> À : sos at the-doors.enix.org
> Objet : Re: [SOS] Pagination
> 
> 
> Salut,
> 
> [ Le mail est long, mais je crois que la solution est au milieu ;-) ]
> 
> On Thu, 20 Oct 2005 18:44:34 +0200
> KAISER Edouard <edouard.kaiser at gmail.com> wrote:
> 
> > /* 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));
> 
> À tout hasard, tu as vérifié que sizeof(struct 
> x86_page_table_entry) est bien égal à 4 ?
> 
> > 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;
> 
> À mon avis ici, ça serait plus simple de supposer que 
> Page_Table_1 est forcément alignée sur une frontière de 4k 
> octets. Je ne pense pas que ce soit la peine de faire 
> l'alignement toi-même: si elle n'est pas alignée, c'est qu'il 
> y a un problème dans ton code. Autant ne pas le cacher.
> 
> >         /*----------------------*/
> > 	Page_Directory->PageTable_Address = Page_Table_Address;
> > 	
> > 	/* Page Directory 2 */
> > 	(Page_Directory+1)->Present0 = 1;
> 
> Tu peux aussi écrire 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;
> 
> Pareil ici.
> 
> >         /*----------------------*/
> >         (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;
> 
> Pareil ici: suppose que Linear_Address est aligné sur une 
> frontière de 4 Ko. Tu peux mettre un truc du genre:
> 
>  ASSERT (PAGE_ALIGN_INF (Linear_Address) == Linear_Address);
> 
> > 	/* On recupere l'adresse de la table des pages 
> correspondantes */
> 
> 
> > Page_Table_Address = (struct 
> > x86_page_table_entry*)((Page_Directory+PDE)->PageTable_Address);
> 
> Je pense que le problème est ici. Le champ PageTable_Address 
> ne contient que les 20 bits de poids fort de l'adresse de la 
> table de pages. Je verrais plutôt un truc du genre:
> 
> Page_Table_Address = 
>    (struct x86_page_table_entry *)
>    (Page_Directory[PDE].PageTable_Address << 12);
> 
> > 	/*
> > 	 * Initialisation des champs dans la table des pages 
> selon l'index 
> > dans
> >      * l'adresse lineaire.
> > 	 */
> > 	(Page_Table_Address+PTE)->Present0 = 1;
> 
> Tu peux aussi écrire 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 
> > !!!
> 
> Le problème là, ce n'est pas vraiment qu'à partir de 0x100000 
> on dépasse les 20 bits. C'est surtout que le processeur veut 
> _seulement_ les 20 bits de poids fort, car de toute façon, 
> les 12 bits de poids faible sont forcément à 0, puisqu'on est 
> aligné sur 4 Ko (2^12 = 4096 = 4 Ko).
> 
> > 	 * 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;
> > }
> 
> > Voila désolés de donner du code comme cela, si vraiment certain 
> > veulent un tarball, je le donnerai =)
> 
> Dans tous les cas, c'est mieux de donner un tarball (enfin 
> l'URL d'un tarball posé sur un FTP quelconque). Ça permet de 
> tester, de débugger, etc. Parfois, juste en lisant le code, 
> ce n'est pas évident de trouver le problème.
> 
> Bonne journée,
> 
> Thomas
> -- 
> PETAZZONI Thomas - thomas.petazzoni at enix.org 
> http://{thomas,sos,kos}.enix.org - Jabber: 
> thomas.petazzoni at jabber.dk http://{agenda,livret}dulibre.org 
> Fingerprint : 0BE1 4CF3 CEA4 AC9D CC6E  1624 F653 CB30 98D3 F7A7
> 




Plus d'informations sur la liste de diffusion Sos