Come posso riservare un blocco di memoria dal kernel Linux?


25

Ho un dispositivo che ha bisogno di un blocco di memoria che è riservato solo per esso, senza l'intervento del sistema operativo. Esiste un modo per dire al BIOS o al sistema operativo che un blocco di memoria è riservato e non deve usarlo?

Sto usando questo dispositivo su una macchina openSUSE.

Risposte:


23

Quello che stai chiedendo si chiama DMA. È necessario scrivere un driver per prenotare questa memoria.

Sì, mi rendo conto che hai detto che non volevi che il sistema operativo intervenisse e un driver diventa parte del sistema operativo, ma in assenza di una prenotazione del driver, il kernel ritiene che tutta la memoria appartenga ad esso. (A meno che tu non dica al kernel di ignorare il blocco di memoria, secondo la risposta di Aaron, cioè.)

Il capitolo 15 (PDF) di " Linux Device Driver, 3 / e " di Rubini, Corbet e Kroah-Hartmann tratta DMA e argomenti correlati.

Se vuoi una versione HTML di questo, ho trovato la versione della seconda edizione del capitolo altrove online. Attenzione che la seconda edizione ha ormai più di un decennio, essendo uscita quando il kernel 2.4 era nuovo. C'è stato molto lavoro sul sottosistema di gestione della memoria del kernel da quei giorni, quindi potrebbe non applicarsi più molto bene.


Con DMA posso scegliere quali indirizzi fisici usare? Il kernel mi darà un blocco contiguo di memoria? È garantito che sia sempre disponibile?
Nathan Fellman,

1
Risposte alle tue domande a partire da pagina 442 del PDF che ti ho indicato.
Warren Young

24

Se vuoi che il sistema operativo lo ignori totalmente , devi creare un buco di memoria usando " memmap." Vedi questo riferimento . Ad esempio, se si desidera 512 M alla barriera da 2 GB, è possibile inserire " memmap=512M$2G" nella riga di comando del kernel.

Dovrai controllare il tuo dmesgper trovare un buco contiguo da rubare in modo da non calpestare alcun dispositivo; che è specifico per la tua scheda madre + schede.

Questo non è il modo consigliato di fare le cose - vedi la risposta di Warren Young per come farlo correttamente (driver del kernel + DMA). Sto rispondendo alla domanda esatta che hai posto. Se hai intenzione di farlo per gli utenti finali, ti odieranno se lo fai a loro ... fidati di me, questa è l'unica ragione per cui conoscevo questa risposta.


Modifica: se stai usando grub2 w / grubby (es. CentOS 7), devi assicurarti di sfuggire a $ . Dovrebbe essercene uno \prima $. Esempio:

$ 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"

1
Mentre la tua risposta risponde direttamente alla mia domanda, la risposta di Warren sembra essere il modo migliore per farlo. :-)
Nathan Fellman

1
@WarrenYoung Non ho alcuna idea ciò che si suppone a che fare con esso. Immagino " uint8_t *ptr = 0x8000000" con il mio esempio? O che potrebbe segfault ... Eh, davvero non lo so. Ancora una volta, conoscevo la risposta perché ero un utente finale di una scheda PCI mal progettata in cui dovevo allocare manualmente un buffer sotto il segno 4G e quindi dire a un driver dove era quello spazio; potrebbe non essere possibile da userland.
Aaron D. Marasco

2
Solo per sorridere, ho cercato un po 'più a fondo in questo, e sembra che tu abbia bisogno MMAP_FIXED | MMAP_ANON. Senza un dispositivo DMA personalizzato qui con cui giocare, non posso dire se effettivamente fa ciò che l'OP voleva, ma la mia scatola CentOS mi ha dato felicemente un blocco di 8 MB a 512 MB quando ho detto memmap=8M$512Min GRUB. Non richiede nemmeno l'accesso come root, come temevo potesse. Ma anche se questo fa la cosa giusta, penso comunque che probabilmente avrai bisogno di un driver per gestire gli interrupt e così via.
Warren Young,

3
@ AaronD.Marasco: No, mmap()le pagine vengono azzerate prima che il codice userland riesca a vederle. È fatto per sicurezza, in modo che i dati non perdano da un processo all'altro. Un altro motivo per utilizzare un driver, poiché potrebbe essere necessario preservare il contenuto del buffer DMA al momento del caricamento del driver. Oh, a proposito, la mmap()chiamata localizzata in modo arbitrario ha successo anche senza l' memmapopzione di avvio del kernel, almeno fino a quando nessuno sta già usando la memoria posizionata dove richiesto. L'opzione di avvio aumenta senza dubbio le possibilità di successo, ma non è strettamente necessario.
Warren Young,

1
@ AaronD.Marasco hmm, ok. interessante. grazie per quel link, è una buona lettura.
Woodrow Barlow,

5

Per riservare un blocco di memoria dal kernel in Linux basato su ARM, è anche possibile utilizzare un reserved-memorynodo nel file della struttura dei dispositivi (dts). Nella documentazione del kernel (vedi qui ), c'è un esempio:

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>;
    };
};

0

Per prima cosa inserisci questo comando, per verificare le tue impostazioni correnti:

sysctl vm.min_free_kbytes

Per modificare il valore impostato, modifica /etc/sysctl.conf. Cerca la linea:

vm.min_free_kbytes=12888

Se non esiste, crealo (insieme al valore desiderato). Sono accettabili i seguenti valori:

8192
12288
16384
20480

8M è estremamente conservatore; può sedere comodamente a 16M. Dopo aver modificato il valore, eseguirlo e non è necessario riavviare:

sudo sysctl -p

2
Per favore, non cancellare i tuoi post; eliminalo o contrassegnalo per un moderatore da rimuovere per te.
Jasonwryan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.