Bagaimana saya bisa memesan satu blok memori dari kernel Linux?

25

Saya memiliki perangkat yang memerlukan blok memori yang disediakan khusus untuk itu, tanpa campur tangan OS. Apakah ada cara untuk memberi tahu BIOS atau OS bahwa blok memori dicadangkan, dan tidak boleh menggunakannya?

Saya menggunakan perangkat ini pada mesin openSUSE.

Nathan Fellman
sumber

Jawaban:

23

Apa yang Anda minta disebut DMA. Anda perlu menulis driver untuk memesan memori ini.

Ya, saya sadar Anda mengatakan Anda tidak ingin OS untuk campur tangan, dan driver menjadi bagian dari OS, tetapi tanpa adanya reservasi pengemudi, kernel percaya semua memori miliknya. (Kecuali Anda memberi tahu kernel untuk mengabaikan blok memori, per jawaban Harun, yaitu.)

Bab 15 (PDF) " Linux Device Drivers, 3 / e " oleh Rubini, Corbet dan Kroah-Hartmann membahas DMA dan topik terkait.

Jika Anda menginginkan versi HTML ini, saya menemukan versi edisi kedua dari bab ini di tempat lain secara online. Berhati-hatilah karena edisi ke-2 sudah lebih dari satu dekade sekarang, telah keluar ketika kernel 2.4 masih baru. Sudah banyak pekerjaan pada subsistem manajemen memori kernel sejak saat itu, jadi mungkin tidak berlaku dengan baik lagi.

Warren Young
sumber
Dengan DMA, bisakah saya memilih alamat fisik apa yang akan digunakan? Apakah kernel akan memberi saya blok memori yang berdekatan? Apakah dijamin selalu tersedia?
Nathan Fellman
1
Pertanyaan Anda dijawab mulai dari halaman 442 dari PDF yang saya tunjukkan kepada Anda.
Warren Young
24

Jika Anda ingin OS untuk benar-benar mengabaikannya, Anda perlu membuat lubang memori menggunakan memmap"" Lihat referensi ini . Sebagai contoh, jika Anda menginginkan 512M pada penghalang 2GB, Anda dapat menempatkan " memmap=512M$2G" pada baris perintah kernel Anda.

Anda perlu memeriksa apakah dmesgada lubang yang berdekatan untuk dicuri sehingga Anda tidak menginjak perangkat apa pun; itu khusus untuk motherboard + kartu Anda.

Ini bukan cara yang disarankan untuk melakukan sesuatu - lihat jawaban Warren Young untuk bagaimana melakukannya dengan benar (driver kernel + DMA). Saya menjawab pertanyaan persis yang Anda tanyakan. Jika Anda berencana membuat ini untuk pengguna akhir, mereka akan membenci Anda jika Anda melakukan ini kepada mereka ... percayalah, itulah satu-satunya alasan saya tahu jawaban ini.


Sunting: Jika Anda menggunakan grub2 w / grubby (mis. CentOS 7), Anda harus memastikan untuk melepaskan $ . Harus ada satu \sebelumnya $. Contoh:

$ 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
sumber
1
Sementara jawaban Anda menjawab pertanyaan saya secara langsung, jawaban Warren tampaknya merupakan cara yang lebih baik untuk menyelesaikannya. :-)
Nathan Fellman
1
@ WarrenYoung Saya tidak tahu apa yang harus Anda lakukan dengan itu. Saya akan menebak " uint8_t *ptr = 0x8000000" dengan contoh saya? Atau itu mungkin segfault ... Hah, aku benar-benar tidak tahu. Sekali lagi, saya tahu jawabannya karena saya adalah pengguna akhir kartu PCI yang dirancang buruk di mana saya harus secara manual mengalokasikan buffer di bawah tanda 4G dan kemudian memberi tahu pengemudi di mana ruang itu; itu tidak mungkin dari userland.
Aaron D. Marasco
2
Hanya untuk menyeringai, saya melihat sedikit lebih dalam tentang ini, dan tampaknya Anda perlu MMAP_FIXED | MMAP_ANON. Tanpa perangkat DMA khusus untuk dimainkan, saya tidak bisa mengatakan apakah itu benar-benar melakukan apa yang diinginkan OP, tetapi kotak CentOS saya dengan senang hati memberi saya blok 8 MB pada 512 MB ketika saya mengatakan memmap=8M$512Mdi GRUB. Bahkan tidak memerlukan akses root, seperti yang saya khawatirkan mungkin. Tetapi bahkan jika ini memang melakukan hal yang benar, saya masih berpikir Anda mungkin akan memerlukan driver untuk menangani interupsi dan semacamnya.
Warren Young
3
@ AaronD.Marasco: Tidak, mmap()halaman akan di-zeroed sebelum kode userland melihatnya. Ini dilakukan untuk keamanan, sehingga data tidak bocor dari satu proses ke proses berikutnya. Alasan lain untuk menggunakan driver, karena Anda mungkin perlu menyimpan konten buffer DMA pada waktu buka driver. Oh dan omong-omong, mmap()panggilan yang ditemukan secara arbitrer berhasil bahkan tanpa memmapopsi boot kernel, setidaknya selama tidak ada yang sudah menggunakan memori yang terletak di mana Anda bertanya. Opsi booting tentu saja meningkatkan peluang keberhasilan, tetapi itu tidak sepenuhnya diperlukan.
Warren Young
1
@ AaronD.Marasco hmm, oke. menarik. terima kasih atas tautannya, itu bacaan yang bagus.
Woodrow Barlow
5

Untuk memesan blok memori dari kernel di Linux berbasis ARM, Anda juga dapat menggunakan reserved-memorysimpul di file tree perangkat Anda (dts). Dalam dokumentasi kernel (lihat di sini ), ada contoh:

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.
sumber
0

Pertama-tama masukkan perintah ini, untuk memeriksa pengaturan Anda saat ini:

sysctl vm.min_free_kbytes

Untuk mengubah nilai yang ditetapkan, edit /etc/sysctl.conf. Cari garis:

vm.min_free_kbytes=12888

Jika tidak ada, buat (bersama dengan nilai yang Anda inginkan). Nilai-nilai berikut dapat diterima:

8192
12288
16384
20480

8M sangat konservatif; itu bisa duduk di 16M dengan nyaman. Setelah Anda mengubah nilainya, jalankan ini dan tidak perlu reboot:

sudo sysctl -p
Michael Mrozek
sumber
2
Tolong jangan kosongkan posting Anda; hapus atau tandai untuk dihapus oleh moderator.
jasonwryan