对于函数 map_memory 的定义来说,它的作用是:为一段给定的虚拟地址区间 [vstart, vend) 建立页表映射,把它线性映射到一段"连续"的物理内存(phys 起始,对应 vstart),并按需分配/填充中间各级页表
在该函数中,默认页表是按顺序依次排列的,在后续正常启动时会重新分配页表,具体过程大概如此

c
/*
* Map memory for specified virtual address range. Each level of page table needed supports
* multiple entries. If a level requires n entries the next page table level is assumed to be
* formed from n pages.
*
* tbl: location of page table
* rtbl: address to be used for first level page table entry (typically tbl + PAGE_SIZE)
* vstart: virtual address of start of range
* vend: virtual address of end of range - we map [vstart, vend - 1]
* flags: flags to use to map last level entries
* phys: physical address corresponding to vstart - physical memory is contiguous
* order: #imm 2log(number of entries in PGD table)
*
* If extra_shift is set, an extra level will be populated if the end address does
* not fit in 'extra_shift' bits. This assumes vend is in the TTBR0 range.
*
* Temporaries: istart, iend, tmp, count, sv - these need to be different registers
* Preserves: vstart, flags
* Corrupts: tbl, rtbl, vend, istart, iend, tmp, count, sv
*/
.macro map_memory, tbl, rtbl, vstart, vend, flags, phys, order, istart, iend, tmp, count, sv, extra_shift
sub \vend, \vend, #1 // vend - 1
add \rtbl, \tbl, #PAGE_SIZE // rtbl = tbl + PAGE_SIZE 这里PAGE_SIZE=4KB,一般是PUD基地址
mov \count, #0 // count = 0
.L_\@:
// 获取页表项索引个数和具体索引值
compute_indices \vstart, \vend, #PGDIR_SHIFT, #\order, \istart, \iend, \count
// sv = rtbl
mov \sv, \rtbl
populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
mov \tbl, \sv
#if SWAPPER_PGTABLE_LEVELS > 2
// 同上,不同的此处的SWAPPER_TABLE_SHIFT是PUD或者PMD shift
compute_indices \vstart, \vend, #SWAPPER_TABLE_SHIFT, #(PAGE_SHIFT - 3), \istart, \iend, \count
mov \sv, \rtbl
populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
mov \tbl, \sv
#endif
compute_indices \vstart, \vend, #SWAPPER_BLOCK_SHIFT, #(PAGE_SHIFT - 3), \istart, \iend, \count
bic \rtbl, \phys, #SWAPPER_BLOCK_SIZE - 1
populate_entries \tbl, \rtbl, \istart, \iend, \flags, #SWAPPER_BLOCK_SIZE, \tmp
.endm
compute_indices 的作用是在某一级页表(根据 order/shift )上,把虚拟地址区间 [vstart, vend) 转换为该级页表的起始表项索引 [istart, iend,并通过 count 返回
如对于PGD来说,无上级页表,那么 count 为0,那么所有的页表项索引均在当前页表中
c
/*
* Compute indices of table entries from virtual address range. If multiple entries
* were needed in the previous page table level then the next page table level is assumed
* to be composed of multiple pages. (This effectively scales the end index).
*
* vstart: virtual address of start of range
* vend: virtual address of end of range - we map [vstart, vend]
* shift: shift used to transform virtual address into index
* order: #imm 2log(number of entries in page table)
* istart: index in table corresponding to vstart
* iend: index in table corresponding to vend
* count: On entry: how many extra entries were required in previous level, scales
* our end index.
* On exit: returns how many extra entries required for next page table level
*
* Preserves: vstart, vend
* Returns: istart, iend, count
*/
.macro compute_indices, vstart, vend, shift, order, istart, iend, count
// 页表项索引 istart
ubfx \istart, \vstart, \shift, \order
// 页表项索引 iend,不一定是当前页表
ubfx \ , \vend, \shift, \order
// 根据count,把 iend 变成跨多页的线性下标
add \iend, \iend, \count, lsl \order
// 计算总共需要多少个本级页表索引个数
sub \count, \iend, \istart
.endm
populate_entries 在当前页表中,从 index 到 eindex 这一段页表依次写入一个条目,大小是一个PMD页表(一般是页PAGE_SIZE)大小,最后返回更新后的 rtbl
c
/*
* Macro to populate page table entries, these entries can be pointers to the next level
* or last level entries pointing to physical memory.
*
* tbl: page table address
* rtbl: pointer to page table or physical memory
* index: start index to write
* eindex: end index to write - [index, eindex] written to
* flags: flags for pagetable entry to or in
* inc: increment to rtbl between each entry
* tmp1: temporary variable
*
* Preserves: tbl, eindex, flags, inc
* Corrupts: index, tmp1
* Returns: rtbl
*/
.macro populate_entries, tbl, rtbl, index, eindex, flags, inc, tmp1
.Lpe\@: phys_to_pte \tmp1, \rtbl
orr \tmp1, \tmp1, \flags // tmp1 = table entry
str \tmp1, [\tbl, \index, lsl #3]
add \rtbl, \rtbl, \inc // rtbl = pa next level
add \index, \index, #1
cmp \index, \eindex
b.ls .Lpe\@
.endm