162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/mm/proc-v7-3level.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2001 Deep Blue Solutions Ltd. 662306a36Sopenharmony_ci * Copyright (C) 2011 ARM Ltd. 762306a36Sopenharmony_ci * Author: Catalin Marinas <catalin.marinas@arm.com> 862306a36Sopenharmony_ci * based on arch/arm/mm/proc-v7-2level.S 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <asm/assembler.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define TTB_IRGN_NC (0 << 8) 1362306a36Sopenharmony_ci#define TTB_IRGN_WBWA (1 << 8) 1462306a36Sopenharmony_ci#define TTB_IRGN_WT (2 << 8) 1562306a36Sopenharmony_ci#define TTB_IRGN_WB (3 << 8) 1662306a36Sopenharmony_ci#define TTB_RGN_NC (0 << 10) 1762306a36Sopenharmony_ci#define TTB_RGN_OC_WBWA (1 << 10) 1862306a36Sopenharmony_ci#define TTB_RGN_OC_WT (2 << 10) 1962306a36Sopenharmony_ci#define TTB_RGN_OC_WB (3 << 10) 2062306a36Sopenharmony_ci#define TTB_S (3 << 12) 2162306a36Sopenharmony_ci#define TTB_EAE (1 << 31) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* PTWs cacheable, inner WB not shareable, outer WB not shareable */ 2462306a36Sopenharmony_ci#define TTB_FLAGS_UP (TTB_IRGN_WB|TTB_RGN_OC_WB) 2562306a36Sopenharmony_ci#define PMD_FLAGS_UP (PMD_SECT_WB) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */ 2862306a36Sopenharmony_ci#define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA) 2962306a36Sopenharmony_ci#define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#ifndef __ARMEB__ 3262306a36Sopenharmony_ci# define rpgdl r0 3362306a36Sopenharmony_ci# define rpgdh r1 3462306a36Sopenharmony_ci#else 3562306a36Sopenharmony_ci# define rpgdl r1 3662306a36Sopenharmony_ci# define rpgdh r0 3762306a36Sopenharmony_ci#endif 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * cpu_v7_switch_mm(pgd_phys, tsk) 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Set the translation table base pointer to be pgd_phys (physical address of 4362306a36Sopenharmony_ci * the new TTB). 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ciENTRY(cpu_v7_switch_mm) 4662306a36Sopenharmony_ci#ifdef CONFIG_MMU 4762306a36Sopenharmony_ci mmid r2, r2 4862306a36Sopenharmony_ci asid r2, r2 4962306a36Sopenharmony_ci orr rpgdh, rpgdh, r2, lsl #(48 - 32) @ upper 32-bits of pgd 5062306a36Sopenharmony_ci mcrr p15, 0, rpgdl, rpgdh, c2 @ set TTB 0 5162306a36Sopenharmony_ci isb 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci ret lr 5462306a36Sopenharmony_ciENDPROC(cpu_v7_switch_mm) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#ifdef __ARMEB__ 5762306a36Sopenharmony_ci#define rl r3 5862306a36Sopenharmony_ci#define rh r2 5962306a36Sopenharmony_ci#else 6062306a36Sopenharmony_ci#define rl r2 6162306a36Sopenharmony_ci#define rh r3 6262306a36Sopenharmony_ci#endif 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* 6562306a36Sopenharmony_ci * cpu_v7_set_pte_ext(ptep, pte) 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * Set a level 2 translation table entry. 6862306a36Sopenharmony_ci * - ptep - pointer to level 3 translation table entry 6962306a36Sopenharmony_ci * - pte - PTE value to store (64-bit in r2 and r3) 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_ciENTRY(cpu_v7_set_pte_ext) 7262306a36Sopenharmony_ci#ifdef CONFIG_MMU 7362306a36Sopenharmony_ci tst rl, #L_PTE_VALID 7462306a36Sopenharmony_ci beq 1f 7562306a36Sopenharmony_ci tst rh, #1 << (57 - 32) @ L_PTE_NONE 7662306a36Sopenharmony_ci bicne rl, #L_PTE_VALID 7762306a36Sopenharmony_ci bne 1f 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci eor ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to 8062306a36Sopenharmony_ci @ test for !L_PTE_DIRTY || L_PTE_RDONLY 8162306a36Sopenharmony_ci tst ip, #1 << (55 - 32) | 1 << (58 - 32) 8262306a36Sopenharmony_ci orrne rl, #PTE_AP2 8362306a36Sopenharmony_ci biceq rl, #PTE_AP2 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci1: strd r2, r3, [r0] 8662306a36Sopenharmony_ci ALT_SMP(W(nop)) 8762306a36Sopenharmony_ci ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte 8862306a36Sopenharmony_ci#endif 8962306a36Sopenharmony_ci ret lr 9062306a36Sopenharmony_ciENDPROC(cpu_v7_set_pte_ext) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* 9362306a36Sopenharmony_ci * Memory region attributes for LPAE (defined in pgtable-3level.h): 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * n = AttrIndx[2:0] 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * n MAIR 9862306a36Sopenharmony_ci * UNCACHED 000 00000000 9962306a36Sopenharmony_ci * BUFFERABLE 001 01000100 10062306a36Sopenharmony_ci * DEV_WC 001 01000100 10162306a36Sopenharmony_ci * WRITETHROUGH 010 10101010 10262306a36Sopenharmony_ci * WRITEBACK 011 11101110 10362306a36Sopenharmony_ci * DEV_CACHED 011 11101110 10462306a36Sopenharmony_ci * DEV_SHARED 100 00000100 10562306a36Sopenharmony_ci * DEV_NONSHARED 100 00000100 10662306a36Sopenharmony_ci * unused 101 10762306a36Sopenharmony_ci * unused 110 10862306a36Sopenharmony_ci * WRITEALLOC 111 11111111 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci.equ PRRR, 0xeeaa4400 @ MAIR0 11162306a36Sopenharmony_ci.equ NMRR, 0xff000004 @ MAIR1 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* 11462306a36Sopenharmony_ci * Macro for setting up the TTBRx and TTBCR registers. 11562306a36Sopenharmony_ci * - \ttbr1 updated. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci .macro v7_ttb_setup, zero, ttbr0l, ttbr0h, ttbr1, tmp 11862306a36Sopenharmony_ci ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address 11962306a36Sopenharmony_ci cmp \ttbr1, \tmp, lsr #12 @ PHYS_OFFSET > PAGE_OFFSET? 12062306a36Sopenharmony_ci mov \tmp, #TTB_EAE @ for TTB control egister 12162306a36Sopenharmony_ci ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP) 12262306a36Sopenharmony_ci ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP) 12362306a36Sopenharmony_ci ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP << 16) 12462306a36Sopenharmony_ci ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP << 16) 12562306a36Sopenharmony_ci /* 12662306a36Sopenharmony_ci * Only use split TTBRs if PHYS_OFFSET <= PAGE_OFFSET (cmp above), 12762306a36Sopenharmony_ci * otherwise booting secondary CPUs would end up using TTBR1 for the 12862306a36Sopenharmony_ci * identity mapping set up in TTBR0. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ 13162306a36Sopenharmony_ci mcr p15, 0, \tmp, c2, c0, 2 @ TTBCR 13262306a36Sopenharmony_ci mov \tmp, \ttbr1, lsr #20 13362306a36Sopenharmony_ci mov \ttbr1, \ttbr1, lsl #12 13462306a36Sopenharmony_ci addls \ttbr1, \ttbr1, #TTBR1_OFFSET 13562306a36Sopenharmony_ci mcrr p15, 1, \ttbr1, \tmp, c2 @ load TTBR1 13662306a36Sopenharmony_ci .endm 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* 13962306a36Sopenharmony_ci * AT 14062306a36Sopenharmony_ci * TFR EV X F IHD LR S 14162306a36Sopenharmony_ci * .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM 14262306a36Sopenharmony_ci * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced 14362306a36Sopenharmony_ci * 11 0 110 0 0011 1100 .111 1101 < we want 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci .align 2 14662306a36Sopenharmony_ci .type v7_crval, #object 14762306a36Sopenharmony_civ7_crval: 14862306a36Sopenharmony_ci crval clear=0x0122c302, mmuset=0x30c03c7d, ucset=0x00c01c7c 149