root/arch/arm/mm/proc-v7-2level.S
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * arch/arm/mm/proc-v7-2level.S
 *
 * Copyright (C) 2001 Deep Blue Solutions Ltd.
 */

#define TTB_S           (1 << 1)
#define TTB_RGN_NC      (0 << 3)
#define TTB_RGN_OC_WBWA (1 << 3)
#define TTB_RGN_OC_WT   (2 << 3)
#define TTB_RGN_OC_WB   (3 << 3)
#define TTB_NOS         (1 << 5)
#define TTB_IRGN_NC     ((0 << 0) | (0 << 6))
#define TTB_IRGN_WBWA   ((0 << 0) | (1 << 6))
#define TTB_IRGN_WT     ((1 << 0) | (0 << 6))
#define TTB_IRGN_WB     ((1 << 0) | (1 << 6))

/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
#define TTB_FLAGS_UP    TTB_IRGN_WB|TTB_RGN_OC_WB
#define PMD_FLAGS_UP    PMD_SECT_WB

/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
#define TTB_FLAGS_SMP   TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
#define PMD_FLAGS_SMP   PMD_SECT_WBWA|PMD_SECT_S

.arch armv7-a

/*
 *      cpu_v7_switch_mm(pgd_phys, tsk)
 *
 *      Set the translation table base pointer to be pgd_phys
 *
 *      - pgd_phys - physical address of new TTB
 *
 *      It is assumed that:
 *      - we are not using split page tables
 *
 *      Note that we always need to flush BTAC/BTB if IBE is set
 *      even on Cortex-A8 revisions not affected by 430973.
 *      If IBE is not set, the flush BTAC/BTB won't do anything.
 */
SYM_TYPED_FUNC_START(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
        mmid    r1, r1                          @ get mm->context.id
        ALT_SMP(orr     r0, r0, #TTB_FLAGS_SMP)
        ALT_UP(orr      r0, r0, #TTB_FLAGS_UP)
#ifdef CONFIG_PID_IN_CONTEXTIDR
        mrc     p15, 0, r2, c13, c0, 1          @ read current context ID
        lsr     r2, r2, #8                      @ extract the PID
        bfi     r1, r2, #8, #24                 @ insert into new context ID
#endif
#ifdef CONFIG_ARM_ERRATA_754322
        dsb
#endif
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID
        isb
        mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
        isb
#endif
        bx      lr
SYM_FUNC_END(cpu_v7_switch_mm)

/*
 *      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
 */
SYM_TYPED_FUNC_START(cpu_v7_set_pte_ext)
#ifdef 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

        tst     r1, #1 << 4
        orrne   r3, r3, #PTE_EXT_TEX(1)

        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

        tst     r1, #L_PTE_XN
        orrne   r3, r3, #PTE_EXT_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

 ARM(   str     r3, [r0, #2048]! )
 THUMB( add     r0, r0, #2048 )
 THUMB( str     r3, [r0] )
        ALT_SMP(W(nop))
        ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
#endif
        bx      lr
SYM_FUNC_END(cpu_v7_set_pte_ext)

        /*
         * Memory region attributes with SCTLR.TRE=1
         *
         *   n = TEX[0],C,B
         *   TR = PRRR[2n+1:2n]         - memory type
         *   IR = NMRR[2n+1:2n]         - inner cacheable property
         *   OR = NMRR[2n+17:2n+16]     - outer cacheable property
         *
         *                      n       TR      IR      OR
         *   UNCACHED           000     00
         *   BUFFERABLE         001     10      00      00
         *   WRITETHROUGH       010     10      10      10
         *   WRITEBACK          011     10      11      11
         *   reserved           110
         *   WRITEALLOC         111     10      01      01
         *   DEV_SHARED         100     01
         *   DEV_NONSHARED      100     01
         *   DEV_WC             001     10
         *   DEV_CACHED         011     10
         *
         * Other attributes:
         *
         *   DS0 = PRRR[16] = 0         - device shareable property
         *   DS1 = PRRR[17] = 1         - device shareable property
         *   NS0 = PRRR[18] = 0         - normal shareable property
         *   NS1 = PRRR[19] = 1         - normal shareable property
         *   NOS = PRRR[24+n] = 1       - not outer shareable
         */
.equ    PRRR,   0xff0a81a8
.equ    NMRR,   0x40e040e0

        /*
         * Macro for setting up the TTBRx and TTBCR registers.
         * - \ttb0 and \ttb1 updated with the corresponding flags.
         */
        .macro  v7_ttb_setup, zero, ttbr0l, ttbr0h, ttbr1, tmp
        mcr     p15, 0, \zero, c2, c0, 2        @ TTB control register
        ALT_SMP(orr     \ttbr0l, \ttbr0l, #TTB_FLAGS_SMP)
        ALT_UP(orr      \ttbr0l, \ttbr0l, #TTB_FLAGS_UP)
        ALT_SMP(orr     \ttbr1, \ttbr1, #TTB_FLAGS_SMP)
        ALT_UP(orr      \ttbr1, \ttbr1, #TTB_FLAGS_UP)
        mcr     p15, 0, \ttbr1, c2, c0, 1       @ load TTB1
        .endm

        /*   AT
         *  TFR   EV X F   I D LR    S
         * .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
         * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
         *   01    0 110       0011 1100 .111 1101 < we want
         */
        .align  2
        .type   v7_crval, #object
v7_crval:
        crval   clear=0x2120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c