1. 程式人生 > 其它 >linux aarch64 head.S map_memory

linux aarch64 head.S map_memory

 

註釋寫的很詳細了。

對映一段 VA 地址。

輸入引數:

tbl  table location - 使用呼叫前 設定的值

rtbl  - 會覆蓋為  rtbl = tbl + PAGE_SIZE, 所以呼叫前的值不關心。

vstart  虛擬地址的起始值 使用呼叫前 設定的值

vend  虛擬地址的結束值  使用呼叫前 設定的值

flags     最後一層 頁表  block descriptor  裡面 使用  的 flags

phys    實體地址的起始值。

pgds     page global dirs 的個數。

=============

呼叫一次 map_memory 後,   傳入的  vstart  vend  flags 不會被改變; tbl   rtbl  會被改變

 

反覆的呼叫 compute_indices 計算值,然後呼叫 populate_enties 填寫值。

 

 224/*
 225 * Map memory for specified virtual address range. Each level of page table needed supports
 226 * multiple entries. If a level requires n entries the next page table level is assumed to be
 227 * formed from n pages.
 228 *
 229 *      tbl:    location of page table
 230 *      rtbl:   address to be used for first level page table entry (typically tbl + PAGE_SIZE)
 231 *      vstart: start address to map
 232 *      vend:   end address to map - we map [vstart, vend]
 233 *      flags:  flags to use to map last level entries
 234 *      phys:   physical address corresponding to vstart - physical memory is contiguous
 235 *      pgds:   the number of pgd entries
 236 *
 237 * Temporaries: istart, iend, tmp, count, sv - these need to be different registers
 238 * Preserves:   vstart, vend, flags
 239 * Corrupts:    tbl, rtbl, istart, iend, tmp, count, sv
 240 
*/ 241 .macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv 242 add \rtbl, \tbl, #PAGE_SIZE 243 mov \sv, \rtbl 244 mov \count, #0 245 compute_indices \vstart, \vend, #PGDIR_SHIFT, \pgds, \istart, \iend, \count 246 populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
247 mov \tbl, \sv 248 mov \sv, \rtbl 249 250#if SWAPPER_PGTABLE_LEVELS > 3 251 compute_indices \vstart, \vend, #PUD_SHIFT, #PTRS_PER_PUD, \istart, \iend, \count 252 populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp 253 mov \tbl, \sv 254 mov \sv, \rtbl 255#endif 256 257#if SWAPPER_PGTABLE_LEVELS > 2 258 compute_indices \vstart, \vend, #SWAPPER_TABLE_SHIFT, #PTRS_PER_PMD, \istart, \iend, \count 259 populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp 260 mov \tbl, \sv 261#endif 262 263 compute_indices \vstart, \vend, #SWAPPER_BLOCK_SHIFT, #PTRS_PER_PTE, \istart, \iend, \count 264 bic \count, \phys, #SWAPPER_BLOCK_SIZE - 1 265 populate_entries \tbl, \count, \istart, \iend, \flags, #SWAPPER_BLOCK_SIZE, \tmp 266 .endm

 

compute_indices 

輸入:

vstart  vend  虛擬地址的起始和結尾

shift  虛擬地址中,頁表 index 對應的 bit 位的起始 shift 值。比如 pgd  也表 index 使用 47 ~ 39 bits, 那麼shift 就是 39 。

ptrs  也表中,總的表項的個數,比如 512個。說明這個 頁表 使用的 VA bits 為 9 個 bits.

count  上一級頁表 中,有幾個 頁表 項。

 

臨時變數: istart  iend

 

輸出

istart  vstart 地址在 頁表 中對應的 index

iend   vend 地址在 頁表 中 對應 的  index

count  count = iend - istart ; 需要的表 項 的個數。

 

188/*
 189 * Compute indices of table entries from virtual address range. If multiple entries
 190 * were needed in the previous page table level then the next page table level is assumed
 191 * to be composed of multiple pages. (This effectively scales the end index).
 192 *
 193 *      vstart: virtual address of start of range
 194 *      vend:   virtual address of end of range
 195 *      shift:  shift used to transform virtual address into index
 196 *      ptrs:   number of entries in page table
 197 *      istart: index in table corresponding to vstart
 198 *      iend:   index in table corresponding to vend
 199 *      count:  On entry: how many extra entries were required in previous level, scales
 200 *                        our end index.
 201 *              On exit: returns how many extra entries required for next page table level
 202 *
 203 * Preserves:   vstart, vend, shift, ptrs
 204 * Returns:     istart, iend, count
 205 */
 206        .macro compute_indices, vstart, vend, shift, ptrs, istart, iend, count
 207        lsr     \iend, \vend, \shift
 208        mov     \istart, \ptrs
 209        sub     \istart, \istart, #1
 210        and     \iend, \iend, \istart   // iend = (vend >> shift) & (ptrs - 1)
 211        mov     \istart, \ptrs
 212        mul     \istart, \istart, \count
 213        add     \iend, \iend, \istart   // iend += count * ptrs
 214                                        // our entries span multiple tables
 215
 216        lsr     \istart, \vstart, \shift
 217        mov     \count, \ptrs
 218        sub     \count, \count, #1
 219        and     \istart, \istart, \count
 220
 221        sub     \count, \iend, \istart
 222        .endm

207 ~ 210  iend = ( vend >> shift ) & ( ptrs - 1)

211 ~ 213  處理 count 對  iend  的影響。 count 表示 上一級頁表 中 表項  的個數。 0 個表示 1 個, 1 表示2個。 註釋有點錯誤,應該是 iend = iend + count * ptrs .

 

舉例:要對映的 VA start 到 VA end 很大一塊區域,需要兩個 pdg 專案

VA start   0x0000 0000 0000 0000   //  bit 39 為 0.

VA end    0x0000 0040 0000 0000  // 8 = 0b1000 ,即 bit 39 為 1

map_memory 中的  

244 ~ 245 行。 

compute_indices 的輸入: vstart=0x0000 0000 0000 0000   vend=0x0000 0040 0000 0000  shift = #PGDIR_SHIFT (39),   ptrs=\pgds (512) 傳入 compute_indices ;   count 設定為 0 (因為比 pgd 更高一層的 頁表專案個是就是 0 個)

輸出: istart = 0, iend = 1, count = 1;

246 行, 使用 populate_entries  , 在tbl 地址上面建立表,填充了 0 , 1 兩個 表項, 表項裡面填充 指向下一級 頁表 的地址 rtbl 

 244        mov \count, #0
 245        compute_indices \vstart, \vend, #PGDIR_SHIFT, \pgds, \istart, \iend, \count
 246        populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp

下一級  pud 頁表填充時,即需要考慮 pgd 中 表項的個數了。

251 行 中 count 的值為 1 。 表示 pgd 中填充了 兩個 表項 ,idx 為 0 和 1 的兩項。

            vstart=0x0000 0000 0000 0000   vend=0x0000 0040 0000 0000  shift = #PGDIR_SHIFT (30),   ptrs=\pgds (512)

 249
250#if SWAPPER_PGTABLE_LEVELS > 3

251 compute_indices \vstart, \vend, #PUD_SHIFT, #PTRS_PER_PUD, \istart, \iend, \count 252 populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp

     這時的  compute_indecs 中,

 

iend = ( vend >> 30 ) & ( 512 -1 ) . 注意,這兒只取出了 vend 中的  bit 30 ~ 38 這一段的值,為 0 ( vend 中只有 bit 39 = 1.)

一個 pgd 表項 指向 一張 pud 表,那麼 pgd 有2 個 表項, 就 需要  2 張 pud 表,一張 pud 表中有  ptr 個表項。

所以,我們這兒計算出來的  iend = 0 ,是值 第二張  pud 表中的 index 0 。 所以 ,僅僅通過 207 ~ 218 之間的計算並不完整。需要 211 ~ 213 中的補充

iend = iend + count * ptrs  =  0 + 1 * 512 = 512 ;

istart 的計算, istart = vstart >> 30) & 512  = 0 ;

count = 512 - 0  = 512  . 

及,需要對映 很大一塊VA ,VA start   0x0000 0000 0000 0000   ~  VA end    0x0000 0040 0000 0000  ,需要 513  個 PUD 表項。

 207        lsr     \iend, \vend, \shift
 208        mov     \istart, \ptrs
 209        sub     \istart, \istart, #1
 210        and     \iend, \iend, \istart   // iend = (vend >> shift) & (ptrs - 1)

 211        mov     \istart, \ptrs
 212        mul     \istart, \istart, \count
 213        add     \iend, \iend, \istart   // iend += count * ptrs