1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * arch/arm/mm/proc-v7-3level.S 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2001 Deep Blue Solutions Ltd. 6*4882a593Smuzhiyun * Copyright (C) 2011 ARM Ltd. 7*4882a593Smuzhiyun * Author: Catalin Marinas <catalin.marinas@arm.com> 8*4882a593Smuzhiyun * based on arch/arm/mm/proc-v7-2level.S 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun#include <asm/assembler.h> 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun#define TTB_IRGN_NC (0 << 8) 13*4882a593Smuzhiyun#define TTB_IRGN_WBWA (1 << 8) 14*4882a593Smuzhiyun#define TTB_IRGN_WT (2 << 8) 15*4882a593Smuzhiyun#define TTB_IRGN_WB (3 << 8) 16*4882a593Smuzhiyun#define TTB_RGN_NC (0 << 10) 17*4882a593Smuzhiyun#define TTB_RGN_OC_WBWA (1 << 10) 18*4882a593Smuzhiyun#define TTB_RGN_OC_WT (2 << 10) 19*4882a593Smuzhiyun#define TTB_RGN_OC_WB (3 << 10) 20*4882a593Smuzhiyun#define TTB_S (3 << 12) 21*4882a593Smuzhiyun#define TTB_EAE (1 << 31) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun/* PTWs cacheable, inner WB not shareable, outer WB not shareable */ 24*4882a593Smuzhiyun#define TTB_FLAGS_UP (TTB_IRGN_WB|TTB_RGN_OC_WB) 25*4882a593Smuzhiyun#define PMD_FLAGS_UP (PMD_SECT_WB) 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */ 28*4882a593Smuzhiyun#define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA) 29*4882a593Smuzhiyun#define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun#ifndef __ARMEB__ 32*4882a593Smuzhiyun# define rpgdl r0 33*4882a593Smuzhiyun# define rpgdh r1 34*4882a593Smuzhiyun#else 35*4882a593Smuzhiyun# define rpgdl r1 36*4882a593Smuzhiyun# define rpgdh r0 37*4882a593Smuzhiyun#endif 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun/* 40*4882a593Smuzhiyun * cpu_v7_switch_mm(pgd_phys, tsk) 41*4882a593Smuzhiyun * 42*4882a593Smuzhiyun * Set the translation table base pointer to be pgd_phys (physical address of 43*4882a593Smuzhiyun * the new TTB). 44*4882a593Smuzhiyun */ 45*4882a593SmuzhiyunENTRY(cpu_v7_switch_mm) 46*4882a593Smuzhiyun#ifdef CONFIG_MMU 47*4882a593Smuzhiyun mmid r2, r2 48*4882a593Smuzhiyun asid r2, r2 49*4882a593Smuzhiyun orr rpgdh, rpgdh, r2, lsl #(48 - 32) @ upper 32-bits of pgd 50*4882a593Smuzhiyun mcrr p15, 0, rpgdl, rpgdh, c2 @ set TTB 0 51*4882a593Smuzhiyun isb 52*4882a593Smuzhiyun#endif 53*4882a593Smuzhiyun ret lr 54*4882a593SmuzhiyunENDPROC(cpu_v7_switch_mm) 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun#ifdef __ARMEB__ 57*4882a593Smuzhiyun#define rl r3 58*4882a593Smuzhiyun#define rh r2 59*4882a593Smuzhiyun#else 60*4882a593Smuzhiyun#define rl r2 61*4882a593Smuzhiyun#define rh r3 62*4882a593Smuzhiyun#endif 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun/* 65*4882a593Smuzhiyun * cpu_v7_set_pte_ext(ptep, pte) 66*4882a593Smuzhiyun * 67*4882a593Smuzhiyun * Set a level 2 translation table entry. 68*4882a593Smuzhiyun * - ptep - pointer to level 3 translation table entry 69*4882a593Smuzhiyun * - pte - PTE value to store (64-bit in r2 and r3) 70*4882a593Smuzhiyun */ 71*4882a593SmuzhiyunENTRY(cpu_v7_set_pte_ext) 72*4882a593Smuzhiyun#ifdef CONFIG_MMU 73*4882a593Smuzhiyun tst rl, #L_PTE_VALID 74*4882a593Smuzhiyun beq 1f 75*4882a593Smuzhiyun tst rh, #1 << (57 - 32) @ L_PTE_NONE 76*4882a593Smuzhiyun bicne rl, #L_PTE_VALID 77*4882a593Smuzhiyun bne 1f 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun eor ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to 80*4882a593Smuzhiyun @ test for !L_PTE_DIRTY || L_PTE_RDONLY 81*4882a593Smuzhiyun tst ip, #1 << (55 - 32) | 1 << (58 - 32) 82*4882a593Smuzhiyun orrne rl, #PTE_AP2 83*4882a593Smuzhiyun biceq rl, #PTE_AP2 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun1: strd r2, r3, [r0] 86*4882a593Smuzhiyun ALT_SMP(W(nop)) 87*4882a593Smuzhiyun ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte 88*4882a593Smuzhiyun#endif 89*4882a593Smuzhiyun ret lr 90*4882a593SmuzhiyunENDPROC(cpu_v7_set_pte_ext) 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun /* 93*4882a593Smuzhiyun * Memory region attributes for LPAE (defined in pgtable-3level.h): 94*4882a593Smuzhiyun * 95*4882a593Smuzhiyun * n = AttrIndx[2:0] 96*4882a593Smuzhiyun * 97*4882a593Smuzhiyun * n MAIR 98*4882a593Smuzhiyun * UNCACHED 000 00000000 99*4882a593Smuzhiyun * BUFFERABLE 001 01000100 100*4882a593Smuzhiyun * DEV_WC 001 01000100 101*4882a593Smuzhiyun * WRITETHROUGH 010 10101010 102*4882a593Smuzhiyun * WRITEBACK 011 11101110 103*4882a593Smuzhiyun * DEV_CACHED 011 11101110 104*4882a593Smuzhiyun * DEV_SHARED 100 00000100 105*4882a593Smuzhiyun * DEV_NONSHARED 100 00000100 106*4882a593Smuzhiyun * unused 101 107*4882a593Smuzhiyun * unused 110 108*4882a593Smuzhiyun * WRITEALLOC 111 11111111 109*4882a593Smuzhiyun */ 110*4882a593Smuzhiyun.equ PRRR, 0xeeaa4400 @ MAIR0 111*4882a593Smuzhiyun.equ NMRR, 0xff000004 @ MAIR1 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun /* 114*4882a593Smuzhiyun * Macro for setting up the TTBRx and TTBCR registers. 115*4882a593Smuzhiyun * - \ttbr1 updated. 116*4882a593Smuzhiyun */ 117*4882a593Smuzhiyun .macro v7_ttb_setup, zero, ttbr0l, ttbr0h, ttbr1, tmp 118*4882a593Smuzhiyun ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address 119*4882a593Smuzhiyun cmp \ttbr1, \tmp, lsr #12 @ PHYS_OFFSET > PAGE_OFFSET? 120*4882a593Smuzhiyun mov \tmp, #TTB_EAE @ for TTB control egister 121*4882a593Smuzhiyun ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP) 122*4882a593Smuzhiyun ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP) 123*4882a593Smuzhiyun ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP << 16) 124*4882a593Smuzhiyun ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP << 16) 125*4882a593Smuzhiyun /* 126*4882a593Smuzhiyun * Only use split TTBRs if PHYS_OFFSET <= PAGE_OFFSET (cmp above), 127*4882a593Smuzhiyun * otherwise booting secondary CPUs would end up using TTBR1 for the 128*4882a593Smuzhiyun * identity mapping set up in TTBR0. 129*4882a593Smuzhiyun */ 130*4882a593Smuzhiyun orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ 131*4882a593Smuzhiyun mcr p15, 0, \tmp, c2, c0, 2 @ TTBCR 132*4882a593Smuzhiyun mov \tmp, \ttbr1, lsr #20 133*4882a593Smuzhiyun mov \ttbr1, \ttbr1, lsl #12 134*4882a593Smuzhiyun addls \ttbr1, \ttbr1, #TTBR1_OFFSET 135*4882a593Smuzhiyun mcrr p15, 1, \ttbr1, \tmp, c2 @ load TTBR1 136*4882a593Smuzhiyun .endm 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun /* 139*4882a593Smuzhiyun * AT 140*4882a593Smuzhiyun * TFR EV X F IHD LR S 141*4882a593Smuzhiyun * .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM 142*4882a593Smuzhiyun * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced 143*4882a593Smuzhiyun * 11 0 110 0 0011 1100 .111 1101 < we want 144*4882a593Smuzhiyun */ 145*4882a593Smuzhiyun .align 2 146*4882a593Smuzhiyun .type v7_crval, #object 147*4882a593Smuzhiyunv7_crval: 148*4882a593Smuzhiyun crval clear=0x0122c302, mmuset=0x30c03c7d, ucset=0x00c01c7c 149