J’essaie d’allouer un tampon DMA pour une charge de travail HPC. Il nécessite 64 Go d’espace tampon. Entre le calcul, certaines données sont déchargées sur une carte PCIe. Plutôt que de copier des données dans un tas de tampons dinky de 4 Mo donnés par pci_alloc_consistent, je voudrais juste créer 64 tampons de 1 Go, soutenus par HugePages de 1 Go.
Quelques informations générales: version du kernel: CentOS 6.4 / 2.6.32-358.el6.x86_64 options de démarrage du kernel: hugepagesz = 1g hugepages = 64 default_hugepagesz = 1g
partie pertinente de / proc / meminfo: AnonHugePages: 0 Ko HugePages_Total: 64 HugePages_Free: 64 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 1048576 Ko DirectMap4k: 848 Ko DirectMap2M: 2062336 Ko DirectMap1G: 132120576 Ko
Je peux monter -t hugetlbfs nodev / mnt / hugepages. CONFIG_HUGETLB_PAGE est vrai. MAP_HUGETLB est défini.
J’ai lu quelques informations sur l’utilisation de libhugetlbfs pour appeler get_huge_pages () dans l’espace utilisateur, mais idéalement, ce tampon serait alloué dans l’espace du kernel. J’ai essayé d’appeler do_mmap () avec MAP_HUGETLB mais cela ne semblait pas changer le nombre d’énormes pages gratuites, donc je ne pense pas que ce soit en fait une sauvegarde des pages massives.
Donc je suppose ce que je veux dire, y a-t-il un moyen de mapper un tampon sur un HugePage de 1 Go dans l’espace kernel, ou faut-il le faire dans l’espace utilisateur? Ou si quelqu’un sait d’une autre manière, je peux obtenir une quantité énorme (1-64 Go) de mémoire physique contiguë disponible en tant que tampon du kernel?
Ceci n’est généralement pas fait dans l’espace kernel, donc pas trop d’exemples.
Comme toute autre page, des pages énormes sont allouées avec alloc_pages, à la mélodie:
struct page *p = alloc_pages(GFP_TRANSHUGE, HPAGE_PMD_ORDER);
HPAGE_PMD_ORDER est une macro définissant un ordre d’une page unique énorme en termes de pages normales. Ce qui précède implique que les énormes pages transparentes sont activées dans le kernel.
Ensuite, vous pouvez continuer à mapper le pointeur de page obtenu de la manière habituelle avec kmap ().
Disclaimer: Je n’ai jamais essayé moi-même, alors vous devrez peut-être faire des essais. Une chose à vérifier est la suivante: HPAGE_PMD_SHIFT représente un ordre d’une plus petite page “énorme”. Si vous souhaitez utiliser ces pages géantes de 1 Go, vous devrez probablement essayer un autre ordre, probablement PUD_SHIFT – PAGE_SHIFT.
PROBLÈME
EUREKA
Mais la fonction existe! Enfouie profondément dans le code source du kernel 2.6, cette fonction permet d’obtenir une page de structure à partir d’une adresse virtuelle, marquée “juste pour les tests” et bloquée avec #if 0:
#if 0 /* This is just for testing */ struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { unsigned long start = address; int length = 1; int nr; struct page *page; struct vm_area_struct *vma; vma = find_vma(mm, addr); if (!vma || !is_vm_hugetlb_page(vma)) return ERR_PTR(-EINVAL); pte = huge_pte_offset(mm, address); /* hugetlb should be locked, and hence, prefaulted */ WARN_ON(!pte || pte_none(*pte)); page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; WARN_ON(!PageHead(page)); return page; }
SOLUTION: Étant donné que la fonction ci-dessus n’est pas réellement compilée dans le kernel, vous devrez l’append à votre source de pilote.
FLUX DE TRAVAIL DU CÔTÉ UTILISATEUR
FLUX DE TRAVAIL DE CONDUCTEUR DE KERNEL
AVERTISSEMENT