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