LINUX預留內存的實現

      在LINUX應用開發中,可能需要使用連續的物理地址來存儲一些數據或者進行DMA操作,但是由於LINUX具備MMU功能,MMU模塊會自動的將物理地址與虛擬地址之間建立頁表對應關係(但並不是線性對應),用戶能訪問的只是虛擬地址,虛擬地址上的連續並不一定代表物理地址上的連續。如果需要使用連續的物理地址,就需要進行預留內存,來將一部分內存保留起來,不用做LINUX建立頁表使用,也就是說用戶程序中是無法直接通過訪問虛擬地址來訪問預留內存的,而是通過/dev/mem的方式來訪問預留內存。

       對於LINUX預留內存的方式,要針對LINUX版本進行區分:

       1.對於無設備樹的LINUX版本,kernel的參數是由uboot直接通過cmdline傳遞過去的,所以只需要修改uboot傳遞給kernel的參數就行。

         Linux內核啓動參數cmdline提供了大量的選項,用來設置內核啓動的參數和配置。其中“mem”選項就是用來限制內核可以看到的系統內存的大小,因此通過設置”mem”參數就能實現保留內存。當”mem”參數指定的size小於系統實際可用的物理內存大小時,實際系統內存中出去mem指定的剩下部分就是reserved memory。例如如果某個系統有64G物理內存,通過添加mem=48G到kernel command line,就能保留最末尾的(64-48)=16G高端內存

 

       2. 對於有設備樹的LINUX版本,kernel的參數是通過設備樹傳入的,因此需要修改設備樹中的內容。Devicetree 提供了兩種方式預留內存:

reserved-memory和memreserve

      

       ◎memreserve用法:在設備樹dts文件中添加如下代碼

    

        /memreserve/ 0x40000000 0x01000000  

     在zynqMP中實現該方法遇到的問題:利用PETALINUX工具來編譯鏡像時,設備樹(dts)是直接由HDF文件生成的,手動去修改dts文件無效,在運行petalinux-build時,手動修改的dts文件會直接被覆蓋掉;但是將該語句添加在system-user.dtsi中,編譯會出現語法錯誤,xilinx論壇上關於此方法出現的問題並未解答。

reserved-memory {

        #address-cells = <1>;

       #size-cells = <1>;

        ranges;



        ipu_cma@90000000 {

            compatible = "shared-dma-pool";

            reg = <0x90000000 0x4000000>;

          reusable;

         status = "okay";

     };

     ◎reserved-memory用法:在設備樹dts文件中添加如下代碼

在zynqMP中實現reserved-memory方法,可以參照LINUX內核源碼的

linux-xlnx-xilinx-v2017.4\Documentation\devicetree\bindings\reserved-memory.txt有以下幾點需要注意:

       (1)針對zynq和zynqMP需要區別對待,address-cells與size-cells需要保持與根節點一致,例如在zynqMP中:

       compatible = "xlnx,zynqmp";

       #address-cells = <2>;

       #size-cells = <2>;

那麼在設備樹中添加reserved-memory節點時,就需要設置爲

       #address-cells = <2>;

       #size-cells = <2>;

       如果設置爲1,內核將無法預留內存,在zynqMP中已經驗證了設置爲1時,預留內存失敗。

       (2)compatible屬性一欄,如果是給特定的驅動使用預留的內存,需要加上compatible,例如給CMA使用的內存。但對於通用性的內存使用,不需要添加compatible欄。

       (3)no-map是將預留內存設置爲不可虛擬地址映射的區域,此處的虛擬地址映射是指利用/dev/mem來訪問物理地址的方法,添加no-map屬性後,只能直接訪問物理地址。

       (4)reusable屬性是將預留內存設置爲操作系統可以使用此區域中的內存擁有該區域的設備驅動程序所需要的限制可以把它收回來。通常這意味着操作系統可以使用該區域存儲易失性或緩存的數據。

      

在system-user.dtsi中添加如下代碼,就可以實現預留內存:    

 reserved-memory {

       #address-cells = <2>;

       #size-cells = <2>;

       ranges;

       reserved: buffer@0 {

           reg = <0x0 0x30000000 0x0 0x10000000>;     

          //將0x30000000-0x40000000總共256M的大小的空間作爲預留內存

       };

   };

     在命令行中輸入:dmesg |grep cma 可以看到如下打印信息:

root@xxx:~# dmesg |grep cma  

[    0.000000] cma: Reserved 256 MiB at 0x0000000020000000

[    0.000000] Memory: 492900K/1048576K available (6652K kernel code, 472K rwdata, 2008K rodata, 448K init, 336K bss, 293532K reserved, 262144K cma-reserved)

其中預留的內存爲:293532K = 286M * 1024 =(256+30*1024,與前面設置的正好對應起來了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章