Comment puis-je réserver un bloc de mémoire du noyau Linux?

26

J'ai un appareil qui a besoin d'un bloc de mémoire qui lui est exclusivement réservé, sans que l'OS n'intervienne. Existe-t-il un moyen de dire au BIOS ou au système d'exploitation qu'un bloc de mémoire est réservé et qu'il ne doit pas l'utiliser?

J'utilise cet appareil sur une machine openSUSE.

Nathan Fellman
la source

Réponses:

24

Ce que vous demandez s'appelle DMA. Vous devez écrire un pilote pour réserver cette mémoire.

Oui, je me rends compte que vous avez dit que vous ne vouliez pas que le système d'exploitation intervienne, et qu'un pilote fasse partie du système d'exploitation, mais en l'absence d'une réservation de pilote, le noyau pense que toute la mémoire lui appartient. (À moins que vous ne disiez au noyau d'ignorer le bloc de mémoire, selon la réponse d'Aaron, c'est-à-dire.)

Le chapitre 15 (PDF) de " Linux Device Drivers, 3 / e " par Rubini, Corbet et Kroah-Hartmann couvre le DMA et les sujets connexes.

Si vous voulez une version HTML de ceci, j'ai trouvé la deuxième édition du chapitre ailleurs en ligne. Attention, la 2e édition a plus de dix ans maintenant, étant sortie lorsque le noyau 2.4 était nouveau. Il y a eu beaucoup de travail sur le sous-système de gestion de la mémoire du noyau depuis ces jours, donc il se peut qu'il ne s'applique plus très bien.

Warren Young
la source
Avec DMA, puis-je choisir les adresses physiques à utiliser? Le noyau me donnera-t-il un bloc de mémoire contigu? Est-il garanti d'être toujours disponible?
Nathan Fellman
1
On répond à vos questions à partir de la page 442 du PDF que je vous ai indiqué.
Warren Young
25

Si vous voulez que le système d'exploitation l' ignore totalement , vous devez faire un trou de mémoire en utilisant " memmap." Voir cette référence . Par exemple, si vous voulez 512M à la barrière de 2 Go, vous pouvez mettre " memmap=512M$2G" sur votre ligne de commande du noyau.

Vous devrez vérifier votre dmesgpour trouver un trou contigu à voler afin de ne pas piétiner sur aucun appareil; qui est spécifique à votre carte mère + cartes.

Ce n'est pas la façon recommandée de faire les choses - voir la réponse de Warren Young pour savoir comment le faire correctement (pilotes du noyau + DMA). Je réponds à la question exacte que vous avez posée. Si vous prévoyez de faire cela pour les utilisateurs finaux, ils vous détesteront si vous leur faites cela ... croyez-moi, c'est la seule raison pour laquelle je connaissais cette réponse.


Edit: Si vous utilisez grub2 w / grubby (par exemple CentOS 7), vous devez vous assurer d'échapper au $ . Il devrait y en avoir un \avant $. Exemple:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"
Aaron D. Marasco
la source
1
Bien que votre réponse réponde directement à ma question, la réponse de Warren semble être la meilleure façon de procéder. :-)
Nathan Fellman
1
@WarrenYoung Je n'ai aucune idée de ce que vous êtes censé en faire. Je devinerais " uint8_t *ptr = 0x8000000" avec mon exemple? Ou cela peut se briser ... Huh, je ne sais vraiment pas. Encore une fois, je connaissais la réponse parce que j'étais un utilisateur final d'une carte PCI mal conçue où je devais allouer manuellement un tampon sous la marque 4G, puis dire à un pilote où se trouvait cet espace; cela peut ne pas être possible depuis l'espace utilisateur.
Aaron D. Marasco
2
Juste pour les sourires, j'ai regardé un peu plus en profondeur, et il semble que vous en ayez besoin MMAP_FIXED | MMAP_ANON. Sans un appareil DMA personnalisé ici pour jouer, je ne peux pas dire s'il fait vraiment ce que l'OP voulait, mais ma boîte CentOS m'a heureusement donné un bloc de 8 Mo à 512 Mo lorsque je l'ai dit memmap=8M$512Mdans GRUB. Il ne nécessite même pas d'accès root, comme je l'avais craint. Mais même si cela fait la bonne chose, je pense toujours que vous aurez probablement besoin d'un pilote pour gérer les interruptions et autres.
Warren Young
3
@ AaronD.Marasco: Non, mmap()les pages d sont mises à zéro avant que le code utilisateur ne puisse les voir. C'est fait pour la sécurité, afin que les données ne fuient pas d'un processus à l'autre. Une autre raison d'utiliser un pilote, car vous devrez peut-être conserver le contenu de la mémoire tampon DMA au moment du chargement du pilote. Oh et en passant, l' mmap()appel localisé arbitrairement réussit même sans l' memmapoption de démarrage du noyau, au moins tant que personne n'utilise déjà la mémoire située là où vous l'avez demandé. L'option de démarrage augmente sans aucun doute les chances de succès, mais ce n'est pas strictement nécessaire.
Warren Young
1
@ AaronD.Marasco hmm, d'accord. intéressant. merci pour ce lien, c'est une bonne lecture.
Woodrow Barlow
5

Pour réserver un bloc de mémoire du noyau dans Linux basé sur ARM, vous pouvez également utiliser un reserved-memorynœud dans votre fichier d'arborescence de périphériques (dts). Dans la documentation du noyau (voir ici ), il y a un exemple:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};
Vladimir S.
la source
0

Entrez d'abord cette commande, pour vérifier votre paramètre actuel:

sysctl vm.min_free_kbytes

Pour modifier la valeur définie, modifiez /etc/sysctl.conf. Recherchez la ligne:

vm.min_free_kbytes=12888

S'il n'existe pas, créez-le (avec la valeur souhaitée). Les valeurs suivantes sont acceptables:

8192
12288
16384
20480

8M est extrêmement conservateur; il peut s'asseoir à 16M confortablement. Une fois que vous avez modifié la valeur, exécutez-la et aucun redémarrage n'est nécessaire:

sudo sysctl -p
Michael Mrozek
la source
2
Veuillez ne pas masquer vos messages; supprimez-le ou marquez-le pour qu'un modérateur le supprime pour vous.
jasonwryan