*参照元 [#j78e2739]
#backlinks

*説明 [#o202c748]
-パス: 複数あり
--CONFIG_ARM_LPAE 無効: [[linux-4.4.1/arch/arm/mm/proc-v7-2level.S]]
--CONFIG_ARM_LPAE 有効: [[linux-4.4.1/arch/arm/mm/proc-v7-3level.S]]
--[[linux-4.4.1/CONFIG_ARM_LPAE]]

-FIXME: これは何?
--ARM のコードは L_PTE_MT_ シリーズのマクロを使って、pte_t の 2~5 ビットの値を変更する。しかし ARMv7 のページテーブルは pte_t とビット配置が異なり、pte をそのままページテーブルのエントリに書きこめない。そのため変換する必要があるのだろう。たぶん。


**引数 [#sa43dcc7]
-ptep
--
-pte
--


**返り値 [#qe3bdba6]
-
--


**参考 [#wab5af0c]

L_PTE_MT_ シリーズの実装。

 arch/arm/include/asm/pgtable-2level.h:
 
 #define L_PTE_MT_UNCACHED       (_AT(pteval_t, 0x00) << 2)      /* 0000 */
 #define L_PTE_MT_BUFFERABLE     (_AT(pteval_t, 0x01) << 2)      /* 0001 */
 #define L_PTE_MT_WRITETHROUGH   (_AT(pteval_t, 0x02) << 2)      /* 0010 */
 #define L_PTE_MT_WRITEBACK      (_AT(pteval_t, 0x03) << 2)      /* 0011 */
 #define L_PTE_MT_MINICACHE      (_AT(pteval_t, 0x06) << 2)      /* 0110 (sa1100, xscale) */
 #define L_PTE_MT_WRITEALLOC     (_AT(pteval_t, 0x07) << 2)      /* 0111 */
 #define L_PTE_MT_DEV_SHARED     (_AT(pteval_t, 0x04) << 2)      /* 0100 */
 #define L_PTE_MT_DEV_NONSHARED  (_AT(pteval_t, 0x0c) << 2)      /* 1100 */
 #define L_PTE_MT_DEV_WC         (_AT(pteval_t, 0x09) << 2)      /* 1001 */
 #define L_PTE_MT_DEV_CACHED     (_AT(pteval_t, 0x0b) << 2)      /* 1011 */
 #define L_PTE_MT_VECTORS        (_AT(pteval_t, 0x0f) << 2)      /* 1111 */
 #define L_PTE_MT_MASK           (_AT(pteval_t, 0x0f) << 2)

 arch/arm/include/asm/pgtable-3level.h:
 
 #define L_PTE_MT_UNCACHED       (_AT(pteval_t, 0) << 2) /* strongly ordered */
 #define L_PTE_MT_BUFFERABLE     (_AT(pteval_t, 1) << 2) /* normal non-cacheable */
 #define L_PTE_MT_WRITETHROUGH   (_AT(pteval_t, 2) << 2) /* normal inner write-through */
 #define L_PTE_MT_WRITEBACK      (_AT(pteval_t, 3) << 2) /* normal inner write-back */
 #define L_PTE_MT_WRITEALLOC     (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */
 #define L_PTE_MT_DEV_SHARED     (_AT(pteval_t, 4) << 2) /* device */
 #define L_PTE_MT_DEV_NONSHARED  (_AT(pteval_t, 4) << 2) /* device */
 #define L_PTE_MT_DEV_WC         (_AT(pteval_t, 1) << 2) /* normal non-cacheable */
 #define L_PTE_MT_DEV_CACHED     (_AT(pteval_t, 3) << 2) /* normal inner write-back */
 #define L_PTE_MT_MASK           (_AT(pteval_t, 7) << 2)


*実装 [#td122eaa]

**CONFIG_ARM_LPAE 無効: arch/arm/mm/proc-v7-2level.S [#o4e2bc40]
 /*
  *      cpu_v7_set_pte_ext(ptep, pte)
  *
  *      Set a level 2 translation table entry.
  *
  *      - ptep  - pointer to level 2 translation table entry
  *                (hardware version is stored at +2048 bytes)
  *      - pte   - PTE value to store
  *      - ext   - value for extended PTE bits
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
-
--[[linux-4.4.1/ENTRY()]]
--[[linux-4.4.1/CONFIG_MMU]]

         str     r1, [r0]                        @ linux version
 
         bic     r3, r1, #0x000003f0
         bic     r3, r3, #PTE_TYPE_MASK
         orr     r3, r3, r2
         orr     r3, r3, #PTE_EXT_AP0 | 2
 
-ptep が指す pte_t の値を r1 と r3 に入れて、r3 の値は下記の加工をする。
--r3 のビット 4~9(AP[0:1], TEX[0:2], AP[2])をクリアする。
--r3 のビット 0, 1(ARM のページテーブル第2レベル記述子の種類を示すビット)をクリアする。
--r3 と引数 ext のビット毎 OR を取って、r3 に入れる。
--r3 の AP[0] を 1 に、bit1(スモールページの意味)を 1 にする。
-PTE_EXT_ 系のビット位置
--PTE_TYPE_MASK: bit0:1, XN と bit1(特に名前がない)
--PTE_EXT_AP0: bit4, AP[0]

         tst     r1, #1 << 4
         orrne   r3, r3, #PTE_EXT_TEX(1)
 
-L_PTE_MT_ シリーズ(ビット 2~5 を占めている)のビット 1、すなわち pte_t のビット 4 を r3 のビット 6(TEX[0])に書く。
-PTE_EXT_ 系のビット位置
--PTE_EXT_TEX(1): bit6

         eor     r1, r1, #L_PTE_DIRTY
         tst     r1, #L_PTE_RDONLY | L_PTE_DIRTY
         orrne   r3, r3, #PTE_EXT_APX
 
         tst     r1, #L_PTE_USER
         orrne   r3, r3, #PTE_EXT_AP1
 
-!RDONLY && DIRTY なら r3 の AP[2] を 0、それ以外は 1 にする。
-USER を r3 の AP[1] にコピーする。
-AP[0] は必ず 1(上の解説参照)なので、ここで AP[2:0] が揃う。
-L_PTE_ 系のビット位置
--L_PTE_DIRTY : bit6(2level), bit55(3level)
--L_PTE_RDONLY: bit7(2level), bit58(3level)
--L_PTE_USER  : bit8(2level), bit6(3level)
-PTE_EXT_ 系のビット位置
--PTE_EXT_APX: bit9, AP[2]
--PTE_EXT_AP1: bit5, AP[1]
-こう設定するので、
|RDONLY|DIRTY|xor DIRTY|AP[2] 結果|
|0     |0    |1        |1         |
|0     |1    |0        |0         |
|1     |0    |1        |1         |
|1     |1    |0        |1         |
|USER  |AP[1] 結果|
|0     |0         |
|1     |1         |
-最終的にはこうなる。
|USER  |RDONLY|DIRTY|AP[2:0] 結果|特権 R|特権 W|ユーザ R|ユーザ W|
|0     |0     |0    |101         |Yes   |No    |No      |No      |
|0     |0     |1    |001         |Yes   |Yes   |No      |No      |
|0     |1     |0    |101         |Yes   |No    |No      |No      |
|0     |1     |1    |101         |Yes   |No    |No      |No      |
|1     |0     |0    |111         |Yes   |No    |Yes     |No      |
|1     |0     |1    |011         |Yes   |Yes   |Yes     |Yes     |
|1     |1     |0    |111         |Yes   |No    |Yes     |No      |
|1     |1     |1    |111         |Yes   |No    |Yes     |No      |

         tst     r1, #L_PTE_XN
         orrne   r3, r3, #PTE_EXT_XN
 
-XN ビットを r3 の XN にコピー。
-L_PTE_ 系のビット位置
--L_PTE_XN: bit9(2level), bit54(3level)
-PTE_EXT_ 系のビット位置
--PTE_EXT_XN: bit0, XN

         tst     r1, #L_PTE_YOUNG
         tstne   r1, #L_PTE_VALID
         eorne   r1, r1, #L_PTE_NONE
         tstne   r1, #L_PTE_NONE
         moveq   r3, #0
 
-YOUNG かつ VALID なのに NONE がセットされていたら、r3 を 0 に、つまり無効なページにする。無効なページにアクセスすると必ずフォールトが発生する。
-L_PTE_ 系のビット位置
--L_PTE_YOUNG: bit1(2level), bit10(3level)
--L_PTE_VALID: bit0(2level), bit0(3level)
--L_PTE_NONE : bit11(2level), bit57(3level)

  ARM(   str     r3, [r0, #2048]! )
  THUMB( add     r0, r0, #2048 )
  THUMB( str     r3, [r0] )
-FIXME: なんで 2048足すの??
-
--[[linux-4.4.1/ARM()]]
--[[linux-4.4.1/THUMB()]]

         ALT_SMP(W(nop))
         ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
-
--[[linux-4.4.1/ALT_SMP()]]
--[[linux-4.4.1/W()]]
--[[linux-4.4.1/ALT_UP()]]

 #endif
         bx      lr
 ENDPROC(cpu_v7_set_pte_ext)
-
--[[linux-4.4.1/ENDPROC()]]


**CONFIG_ARM_LPAE 有効: arch/arm/mm/proc-v7-3level.S [#c917eee9]
 /*
  * cpu_v7_set_pte_ext(ptep, pte)
  *
  * Set a level 2 translation table entry.
  * - ptep - pointer to level 3 translation table entry
  * - pte - PTE value to store (64-bit in r2 and r3)
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
         tst     rl, #L_PTE_VALID
         beq     1f
         tst     rh, #1 << (57 - 32)             @ L_PTE_NONE
         bicne   rl, #L_PTE_VALID
         bne     1f
 
         eor     ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to
                                         @ test for !L_PTE_DIRTY || L_PTE_RDONLY
         tst     ip, #1 << (55 - 32) | 1 << (58 - 32)
         orrne   rl, #PTE_AP2
         biceq   rl, #PTE_AP2
 
 1:      strd    r2, r3, [r0]
         ALT_SMP(W(nop))
         ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
 #endif
         ret     lr
 ENDPROC(cpu_v7_set_pte_ext)


*コメント [#n3bd63a0]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS