| /* |
| * We need constants.h for: |
| * VMA_VM_MM |
| * VMA_VM_FLAGS |
| * VM_EXEC |
| */ |
| #include <asm/asm-offsets.h> |
| #include <asm/thread_info.h> |
| |
| /* |
| * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) |
| */ |
| .macro vma_vm_mm, rd, rn |
| ldr \rd, [\rn, #VMA_VM_MM] |
| .endm |
| |
| /* |
| * vma_vm_flags - get vma->vm_flags |
| */ |
| .macro vma_vm_flags, rd, rn |
| ldr \rd, [\rn, #VMA_VM_FLAGS] |
| .endm |
| |
| .macro tsk_mm, rd, rn |
| ldr \rd, [\rn, #TI_TASK] |
| ldr \rd, [\rd, #TSK_ACTIVE_MM] |
| .endm |
| |
| /* |
| * act_mm - get current->active_mm |
| */ |
| .macro act_mm, rd |
| bic \rd, sp, #8128 |
| bic \rd, \rd, #63 |
| ldr \rd, [\rd, #TI_TASK] |
| ldr \rd, [\rd, #TSK_ACTIVE_MM] |
| .endm |
| |
| /* |
| * mmid - get context id from mm pointer (mm->context.id) |
| */ |
| .macro mmid, rd, rn |
| ldr \rd, [\rn, #MM_CONTEXT_ID] |
| .endm |
| |
| /* |
| * mask_asid - mask the ASID from the context ID |
| */ |
| .macro asid, rd, rn |
| and \rd, \rn, #255 |
| .endm |
| |
| .macro crval, clear, mmuset, ucset |
| #ifdef CONFIG_MMU |
| .word \clear |
| .word \mmuset |
| #else |
| .word \clear |
| .word \ucset |
| #endif |
| .endm |
| |
| /* |
| * cache_line_size - get the cache line size from the CSIDR register |
| * (available on ARMv7+). It assumes that the CSSR register was configured |
| * to access the L1 data cache CSIDR. |
| */ |
| .macro dcache_line_size, reg, tmp |
| mrc p15, 1, \tmp, c0, c0, 0 @ read CSIDR |
| and \tmp, \tmp, #7 @ cache line size encoding |
| mov \reg, #16 @ size offset |
| mov \reg, \reg, lsl \tmp @ actual cache line size |
| .endm |
| |
| |
| /* |
| * Sanity check the PTE configuration for the code below - which makes |
| * certain assumptions about how these bits are layed out. |
| */ |
| #if L_PTE_SHARED != PTE_EXT_SHARED |
| #error PTE shared bit mismatch |
| #endif |
| #if L_PTE_BUFFERABLE != PTE_BUFFERABLE |
| #error PTE bufferable bit mismatch |
| #endif |
| #if L_PTE_CACHEABLE != PTE_CACHEABLE |
| #error PTE cacheable bit mismatch |
| #endif |
| #if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\ |
| L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED |
| #error Invalid Linux PTE bit settings |
| #endif |
| |
| /* |
| * The ARMv6 and ARMv7 set_pte_ext translation function. |
| * |
| * Permission translation: |
| * YUWD APX AP1 AP0 SVC User |
| * 0xxx 0 0 0 no acc no acc |
| * 100x 1 0 1 r/o no acc |
| * 10x0 1 0 1 r/o no acc |
| * 1011 0 0 1 r/w no acc |
| * 110x 0 1 0 r/w r/o |
| * 11x0 0 1 0 r/w r/o |
| * 1111 0 1 1 r/w r/w |
| */ |
| .macro armv6_set_pte_ext |
| str r1, [r0], #-2048 @ linux version |
| |
| bic r3, r1, #0x000003f0 |
| bic r3, r3, #PTE_TYPE_MASK |
| orr r3, r3, r2 |
| orr r3, r3, #PTE_EXT_AP0 | 2 |
| |
| tst r1, #L_PTE_WRITE |
| tstne r1, #L_PTE_DIRTY |
| orreq r3, r3, #PTE_EXT_APX |
| |
| tst r1, #L_PTE_USER |
| orrne r3, r3, #PTE_EXT_AP1 |
| tstne r3, #PTE_EXT_APX |
| bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
| |
| tst r1, #L_PTE_EXEC |
| orreq r3, r3, #PTE_EXT_XN |
| |
| tst r1, #L_PTE_YOUNG |
| tstne r1, #L_PTE_PRESENT |
| moveq r3, #0 |
| |
| str r3, [r0] |
| mcr p15, 0, r0, c7, c10, 1 @ flush_pte |
| .endm |
| |
| |
| /* |
| * The ARMv3, ARMv4 and ARMv5 set_pte_ext translation function, |
| * covering most CPUs except Xscale and Xscale 3. |
| * |
| * Permission translation: |
| * YUWD AP SVC User |
| * 0xxx 0x00 no acc no acc |
| * 100x 0x00 r/o no acc |
| * 10x0 0x00 r/o no acc |
| * 1011 0x55 r/w no acc |
| * 110x 0xaa r/w r/o |
| * 11x0 0xaa r/w r/o |
| * 1111 0xff r/w r/w |
| */ |
| .macro armv3_set_pte_ext wc_disable=1 |
| str r1, [r0], #-2048 @ linux version |
| |
| eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY |
| |
| bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
| bic r2, r2, #PTE_TYPE_MASK |
| orr r2, r2, #PTE_TYPE_SMALL |
| |
| tst r3, #L_PTE_USER @ user? |
| orrne r2, r2, #PTE_SMALL_AP_URO_SRW |
| |
| tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? |
| orreq r2, r2, #PTE_SMALL_AP_UNO_SRW |
| |
| tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
| movne r2, #0 |
| |
| .if \wc_disable |
| #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH |
| tst r2, #PTE_CACHEABLE |
| bicne r2, r2, #PTE_BUFFERABLE |
| #endif |
| .endif |
| str r2, [r0] @ hardware version |
| .endm |
| |
| |
| /* |
| * Xscale set_pte_ext translation, split into two halves to cope |
| * with work-arounds. r3 must be preserved by code between these |
| * two macros. |
| * |
| * Permission translation: |
| * YUWD AP SVC User |
| * 0xxx 00 no acc no acc |
| * 100x 00 r/o no acc |
| * 10x0 00 r/o no acc |
| * 1011 01 r/w no acc |
| * 110x 10 r/w r/o |
| * 11x0 10 r/w r/o |
| * 1111 11 r/w r/w |
| */ |
| .macro xscale_set_pte_ext_prologue |
| str r1, [r0], #-2048 @ linux version |
| |
| eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY |
| |
| bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
| orr r2, r2, #PTE_TYPE_EXT @ extended page |
| |
| tst r3, #L_PTE_USER @ user? |
| orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w |
| |
| tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? |
| orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w |
| @ combined with user -> user r/w |
| .endm |
| |
| .macro xscale_set_pte_ext_epilogue |
| tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
| movne r2, #0 @ no -> fault |
| |
| str r2, [r0] @ hardware version |
| mov ip, #0 |
| mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line |
| mcr p15, 0, ip, c7, c10, 4 @ data write barrier |
| .endm |