Bonjour,
Je travaille actuellement sur le portage d'un driver de Linux 2.4 à Linux 2.6.
Je bloque sur un problème d'ordre memoire que je n'arrive pas à résoudre.
Mon but est de mapper de la mémoire physique de la carte et de la mémoire kernel (des pages).
Je ne suis vraiement pas un grand spécialiste, mais je pense avoir compris le fonctionnement du mapping.
Lorsqu'un programme veut dialoguer avec le driver, il appelle la fonction mmap ainsi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 struct mtp2d_user_map_s *mQp; mQp = mmap(0, sizeof(struct mtp2d_user_map_s), (PROT_READ | PROT_WRITE), MAP_SHARED, mainFD, 0);
La structure correspondante est définie comme suit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 struct mtp2d_user_map_s { struct rxDescriptorTable_s _rx; struct txDescriptorTable_s _tx; struct channel_Buffer_s _rxChBuf[MTP2D_RX_DTAB_ENTRIES]; struct channel_Buffer_s _txChBuf[MTP2D_MAX_CHANNELS][MTP2D_TX_DTAB_ENTRIES_PER_CHANNEL]; struct mtp2d_status_s _status; struct ml2l3i_int_reg_s _ml2l3iReg; };
La fonction mmap fait donc appel à cette fonction dans le driver :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 int mtp2pmc_mmap (struct file *filp, struct vm_area_struct *vmap) { unsigned long regBufferSize; regBufferSize = sizeof(struct mtp2pmc_ml2l3i_int_reg_s); // En 2.4, la fonction est remap_page_range et on enlève le décallage de PAGE_SHIFT au 3ème argument remap_pfn_range(vmap, (vmap->vm_end - regBufferSize)&PAGE_MASK, mtp2pmcRec.ba_ml2l3iFPGA >> PAGE_SHIFT, /* Adresse physique à mapper */ PAGE_SIZE, vmap->vm_page_prot); vmap->vm_ops = &mtp2pmc_vma_ops; mtp2pmc_vma_open(vmap);
Ici, on cherche tout d'abord à mapper le dernier élément de la structure (ml2l3iReg) sur la mémoire physique de la carte. C'est pour cette raison qu'on ne remappe pas de vm_start à vm_end.
A ce point, on a donc mappé uniquement le dernier élément de la structure.
Dans vmap->vm_ops, il est défini une opération nopage. En 2.4, elle est appelée "au besoin" quand le système ne trouve pas de page correspondante. C'est ainsi que sont mappés les autres éléments de la structure (ce sont des pages vides à l'initialisation), et cela fonctionne bien.
Le problème est que je ne retrouve pas le même fonctionnement en 2.6.
En compilant tel quel, je ne mappe que le dernier élément de la structure. Quand le programme cherche à accéder aux autres éléments, le système plante, sans jamais avoir appelé l'opération nopage.
Quand je supprime remap_pfn_range, l'opération nopage est bien appelée et j'accède aux éléments de ma structure mais, forcément, pas au dernier.
Je suppose donc que remap_pfn_range agit sur le système de tel sorte qu'il n'y ai pas d'appel à nopage.
J'ai vu sur internet (et dans LDD3) la description de chacun des deux types de mappage (remap_pfn_range et nopage) séparemment mais je n'ai jamais vu un mélange des deux. Est-ce toujours possible en 2.6 ?
Je peux peut-être m'y prendre autrement, j'avais pensé à mapper la mémoire de la carte dans une page et ensuite gérer cette page comme les autres mais je ne sais pas comment faire.
Je vous remercie par avance pour le temps que vous prendrez.
Partager