*参照元 [#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]