ฉันจะจองบล็อกหน่วยความจำจากเคอร์เนล Linux ได้อย่างไร


25

ฉันมีอุปกรณ์ที่ต้องการบล็อกหน่วยความจำที่สงวนไว้ แต่เพียงผู้เดียวโดยไม่มีระบบปฏิบัติการแทรกแซง มีวิธีใดบ้างที่จะบอก BIOS หรือระบบปฏิบัติการว่ามีการสำรองบล็อกหน่วยความจำไว้และต้องไม่ใช้งานหรือไม่

ฉันใช้อุปกรณ์นี้กับเครื่อง openSUSE

คำตอบ:


23

สิ่งที่คุณขอเรียกว่า DMA คุณต้องเขียนไดรเวอร์เพื่อจองหน่วยความจำนี้

ใช่ฉันรู้ว่าคุณบอกว่าคุณไม่ต้องการให้ระบบปฏิบัติการแทรกแซงและไดรเวอร์กลายเป็นส่วนหนึ่งของระบบปฏิบัติการ แต่ในกรณีที่ไม่มีการจองของไดรเวอร์เคอร์เนลเชื่อว่าหน่วยความจำทั้งหมดเป็นของมัน (เว้นแต่คุณจะบอกเคอร์เนลให้เพิกเฉยต่อบล็อกหน่วยความจำตามคำตอบของแอรอนนั่นคือ)

บทที่ 15 (PDF) ของ " ไดรเวอร์อุปกรณ์ Linux, 3 / e " โดย Rubini, Corbet และ Kroah-Hartmann ครอบคลุม DMA และหัวข้อที่เกี่ยวข้อง

หากคุณต้องการรุ่น HTML นี้ฉันพบบทที่รุ่นที่สองของที่อื่นทางออนไลน์ โปรดระวังว่ารุ่นที่ 2 มีอายุเกินหนึ่งทศวรรษแล้วออกมาเมื่อเคอร์เนล 2.4 เป็นของใหม่ มีงานจำนวนมากในระบบย่อยการจัดการหน่วยความจำของเคอร์เนลตั้งแต่สมัยนั้นดังนั้นมันจึงอาจไม่ได้ใช้งานได้ดีอีกต่อไป


ด้วย DMA ฉันสามารถเลือกที่อยู่ทางกายภาพที่จะใช้ เคอร์เนลจะให้หน่วยความจำต่อเนื่องกับฉันหรือไม่ มันรับประกันว่าจะใช้ได้เสมอหรือไม่?
Nathan Fellman

1
คำถามของคุณจะได้รับคำตอบโดยเริ่มจากหน้า 442 ของ PDF ที่ฉันแนะนำให้คุณ
Warren Young

24

หากคุณต้องการให้ระบบปฏิบัติการเพิกเฉยต่อสิ่งนั้นโดยสิ้นเชิงคุณต้องสร้างรูหน่วยความจำโดยใช้ " memmap." ดูเอกสารอ้างอิงนี้ ตัวอย่างเช่นถ้าคุณต้องการ 512M ที่กั้น 2GB คุณสามารถใส่ " memmap=512M$2G" ในบรรทัดคำสั่งเคอร์เนล

คุณจะต้องตรวจสอบdmesgเพื่อหาช่องโหว่ที่ต่อเนื่องกันเพื่อขโมยดังนั้นคุณจึงไม่เหยียบบนอุปกรณ์ใด ๆ ที่เฉพาะเจาะจงกับเมนบอร์ดของคุณ + การ์ด

นี่ไม่ใช่วิธีที่แนะนำในการทำสิ่งต่าง ๆ - ดูคำตอบของ Warren Young สำหรับวิธีการทำอย่างถูกต้อง (เคอร์เนลไดรเวอร์ + DMA) ฉันกำลังตอบคำถามที่คุณถาม หากคุณวางแผนที่จะทำสิ่งนี้สำหรับผู้ใช้พวกเขาจะเกลียดคุณถ้าคุณทำสิ่งนี้กับพวกเขา ... เชื่อฉันนั่นเป็นเหตุผลเดียวที่ฉันรู้คำตอบนี้


แก้ไข: ถ้าคุณกำลังใช้ grub2 w / สกปรก (เช่น CentOS 7) คุณจะต้องตรวจสอบให้แน่ใจที่จะหลบหนีที่ $ ควรจะมีเพียงครั้งเดียวก่อน\ $ตัวอย่าง:

$ 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
ในขณะที่คำตอบของคุณตอบคำถามของฉันโดยตรงคำตอบของ Warren น่าจะเป็นวิธีที่ดีกว่า :-)
Nathan Fellman

1
@WarrenYoung ฉันมีไม่มีความคิดว่าคุณควรจะทำอย่างไรกับมัน ฉันจะเดา " uint8_t *ptr = 0x8000000" พร้อมกับตัวอย่างของฉันหรือไม่ หรือนั่นอาจ segfault ... อืมฉันไม่รู้จริงๆ อีกครั้งฉันรู้คำตอบเพราะฉันเป็นผู้ใช้ของการ์ด PCI ที่ออกแบบมาไม่ดีซึ่งฉันต้องจัดสรรบัฟเฟอร์ด้วยตนเองด้านล่างเครื่องหมาย 4G จากนั้นบอกคนขับว่าพื้นที่นั้นอยู่ที่ไหน มันอาจเป็นไปไม่ได้จาก userland
Aaron D. Marasco

2
เพียงแค่ให้ยิ้มผมมองเล็ก ๆ น้อย ๆ MMAP_FIXED | MMAP_ANONลึกเข้าไปในนี้และดูเหมือนว่าคุณจำเป็นต้อง หากไม่มีอุปกรณ์ DMA ที่กำหนดเองที่นี่เพื่อเล่นกับฉันไม่สามารถพูดได้ว่ามันเป็นสิ่งที่ OP ต้องการจริง ๆ แต่กล่อง CentOS ของฉันให้บล็อก 8 MB ที่ 512 MB อย่างมีความสุขเมื่อฉันพูดmemmap=8M$512Mใน GRUB มันไม่จำเป็นต้องมีการเข้าถึงรูทเพราะฉันกลัวว่ามันอาจจะ แต่ถึงแม้ว่าสิ่งนี้จะทำในสิ่งที่ถูกต้องฉันยังคงคิดว่าคุณอาจต้องใช้ไดรเวอร์เพื่อจัดการกับการขัดจังหวะและเช่นนั้น
Warren Young

3
@ AaronD.Marasco: ไม่ได้mmap()หน้าเว็บจะเป็นศูนย์ก่อนที่รหัสผู้ใช้จะเห็นหน้าเหล่านั้น มันทำเพื่อความปลอดภัยเพื่อให้ข้อมูลไม่รั่วไหลจากกระบวนการหนึ่งไปยังกระบวนการถัดไป อีกเหตุผลหนึ่งในการใช้ไดรเวอร์เนื่องจากคุณอาจต้องเก็บเนื้อหาของบัฟเฟอร์ DMA ไว้ในขณะโหลดไดรเวอร์ โอ้และโดยวิธีการmmap()โทรที่ตั้งโดยพลการสำเร็จแม้ไม่มีmemmapตัวเลือกการบูตเคอร์เนลอย่างน้อยตราบใดที่ยังไม่มีใครใช้หน่วยความจำที่คุณถาม ตัวเลือกการบูตอย่างไม่ต้องสงสัยเพิ่มโอกาสของความสำเร็จ แต่ไม่จำเป็นอย่างเคร่งครัด
Warren Young

1
@ AaronD.Marasco อืมโอเค น่าสนใจ ขอบคุณสำหรับลิงค์นั้นเป็นการอ่านที่ดี
วูดโรว์บาร์โลว์

5

ในการจองบล็อกหน่วยความจำจากเคอร์เนลใน Linux ที่ใช้ ARM คุณสามารถใช้reserved-memoryโหนดในไฟล์ tree tree (dts) ของอุปกรณ์ของคุณ ในเอกสารประกอบเคอร์เนล (ดูที่นี่ ) มีตัวอย่าง:

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

ก่อนอื่นให้ป้อนคำสั่งนี้เพื่อตรวจสอบการตั้งค่าปัจจุบันของคุณ:

sysctl vm.min_free_kbytes

/etc/sysctl.confการเปลี่ยนค่าที่ตั้งไว้แก้ไข มองหาเส้น:

vm.min_free_kbytes=12888

หากไม่มีอยู่ให้สร้าง (พร้อมกับค่าที่คุณต้องการ) ค่าต่อไปนี้เป็นที่ยอมรับได้:

8192
12288
16384
20480

8M ค่อนข้างอนุรักษ์นิยมมาก สามารถนั่งที่ 16M ได้อย่างสบาย เมื่อคุณเปลี่ยนค่าให้รันสิ่งนี้และไม่จำเป็นต้องรีบูต:

sudo sysctl -p

2
กรุณาอย่าโพสต์ของคุณว่างเปล่า ลบหรือตั้งค่าสถานะสำหรับโมเดอเรเตอร์เพื่อลบให้คุณ
jasonwryan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.