核心分配大塊連續記憶體的方法
引數傳遞:
uboot向核心傳遞引數的方式分為兩類。
(1)第一類是通過boot cmd 例如在uboot終端提示行使用pri命令現實出的boot arg等。
(2)第二類是通過DeviceTree。在/arch/arm/boot/dts/檔案中和定義了和開發板相關的板級描述資訊。
注(1)Device Tree的分析在其它文章中分析
以soc devkit (友晶)為參考在dts目錄下檔案socfpga_cyclone5.dtsi或者socfpga.dts檔案中有以下描述:
memory {
name = "memory";
device_type = "memory";
reg = <0x0 0x40000000>; /* 1 GB */
};
描述了開發辦的實體記憶體使用情況為1G。裝置型別為deivce_type。
在函式:setup_arch()中呼叫setup_machine_fdt()。這個函式引數是__atags_pointer。這個地址是由uboot傳遞。Uboot把控制權交給kernel之前會在R2寄存中存放device tree的線性地址。物理還是虛擬地址?虛擬地址。此地址和實體地址相差一個pgd。即段對映的高12位做基地址。Kernel還沒有真正使用mmu的三級對映方案,還是停留在段對映的空間內。
函式呼叫順序:
setup_arch()
i early_init_dt_scan_memory()
early_init_dt_add_memory_arch()
arm_add_memory()
中作相關處理。主要是把reg欄位解析。最後把base和size等引數存放入相關結構體。這些結構體在下一章中解釋。
uboot cmd 傳遞引數:
static int __init early_mem(char *p)
以上兩種引數傳遞都是通過R2暫存器中的__atags_pointer傳遞。在setup_arch函式中解析。這個函式還是用了cmdline作為引數分析uboot傳遞的引數。
以上兩種方式方法主要初始化以下全域性變數:(memory的使用SOC採用的是Device Tree)
/*
* Memory map description
*/
struct membank {
phys_addr_t start;
phys_addr_t size;
unsigned int highmem;
};
struct meminfo {
int nr_banks;
struct membank bank[NR_BANKS];
};
記憶體描述:
由membank到meminfo的過渡
membank描述了硬體的相關資訊,這些資訊最後落實到linux的管理範圍之內。並且依據處理後的相關資訊分配佈置記憶體空間。這個過程使用到了memblock_type和memblock的資料結構。
struct memblock_type {
unsigned long cnt; /* number of regions */
unsigned long max; /* size of the allocated array */
phys_addr_t total_size; /* size of all regions */
struct memblock_region *regions;
};
struct memblock {
phys_addr_t current_limit;
struct memblock_type memory;
struct memblock_type reserved;
};
Reserved 和memory代表的是保留和實體記憶體描述。可以結合一下列印資訊進行分析。
MEMBLOCK configuration:
memory size = 0x40000000 reserved size = 0x54f553
memory.cnt = 0x1
memory[0x0] [0x00000000000000-0x0000003fffffff], 0x40000000 bytes
reserved.cnt = 0x3
reserved[0x0] [0x00000000004000-0x00000000007fff], 0x4000 bytes
reserved[0x1] [0x000000000081c0-0x0000000054e763], 0x5465a4 bytes
reserved[0x2] [0x00000003ffb000-0x00000003ffffae], 0x4faf bytes
所有保留的資料大小綜合為0x54f553。Memory的區域沒有記錄。只是呼叫create_mapping把這些實體地址建立相應的頁表和葉目錄項。那麼那些記錄為reserve的記憶體大小又是什麼呢?其實這就是核心本身以及device tree 還有一些其它的資料指令段。這些段都是已經存在於記憶體中。並且系統本身以及系統將會用到的資料和指令等,這些資訊非常重要,一定要保留。既然保留,那麼一定是將來的其它管理方案接手並且採用自己的方案管理。但是不會對前一任管理方案所保留的內容進行破壞。
核心記憶體管理方案在初始化和執行時是不同的。初始化偏重於“區分”,而執行時偏重於“效率”。初始化一定要把不同的區域區分明白,告訴後者如何有效管理。至於後者的管理是否和前者衝突,當然有這些reserve的區域來解決。(實際使用更復雜)