summaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/armv8/mmu.h
blob: 39ff74566e20869892bad6847d6129f19a2e3ecc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef _ASM_ARMV8_MMU_H_
#define _ASM_ARMV8_MMU_H_

#ifdef __ASSEMBLY__
#define _AC(X, Y)	X
#else
#define _AC(X, Y)	(X##Y)
#endif

#define UL(x)		_AC(x, UL)

/***************************************************************/
/*
 * The following definitions are related each other, shoud be
 * calculated specifically.
 */

#ifndef CONFIG_SYS_FULL_VA
#define VA_BITS			(42)	/* 42 bits virtual address */
#else
#define VA_BITS			CONFIG_SYS_VA_BITS
#define PTL2_BITS		CONFIG_SYS_PTL2_BITS
#endif

/* PAGE_SHIFT determines the page size */
#undef  PAGE_SIZE
#define PAGE_SHIFT		16
#define PAGE_SIZE		(1 << PAGE_SHIFT)
#define PAGE_MASK		(~(PAGE_SIZE-1))

/*
 * block/section address mask and size definitions.
 */
#ifndef CONFIG_SYS_FULL_VA
#define SECTION_SHIFT		29
#define SECTION_SIZE		(UL(1) << SECTION_SHIFT)
#define SECTION_MASK		(~(SECTION_SIZE-1))
#else
#define BLOCK_SHIFT		CONFIG_SYS_BLOCK_SHIFT
#define BLOCK_SIZE		(UL(1) << BLOCK_SHIFT)
#define BLOCK_MASK		(~(BLOCK_SIZE-1))
#endif

/***************************************************************/

/*
 * Memory types
 */
#define MT_DEVICE_NGNRNE	0
#define MT_DEVICE_NGNRE		1
#define MT_DEVICE_GRE		2
#define MT_NORMAL_NC		3
#define MT_NORMAL		4

#define MEMORY_ATTRIBUTES	((0x00 << (MT_DEVICE_NGNRNE * 8)) |	\
				(0x04 << (MT_DEVICE_NGNRE * 8))   |	\
				(0x0c << (MT_DEVICE_GRE * 8))     |	\
				(0x44 << (MT_NORMAL_NC * 8))      |	\
				(UL(0xff) << (MT_NORMAL * 8)))

/*
 * Hardware page table definitions.
 *
 */

#ifdef CONFIG_SYS_FULL_VA
/*
 * Level 1 descriptor (PGD).
 */

#define PTL1_TYPE_MASK		(3 << 0)
#define PTL1_TYPE_TABLE		(3 << 0)

#define PTL1_TABLE_PXN		(1UL << 59)
#define PTL1_TABLE_XN		(1UL << 60)
#define PTL1_TABLE_AP		(1UL << 61)
#define PTL1_TABLE_NS		(1UL << 63)


/*
 * Level 2 descriptor (PMD).
 */

#define PTL2_TYPE_MASK		(3 << 0)
#define PTL2_TYPE_FAULT		(0 << 0)
#define PTL2_TYPE_TABLE		(3 << 0)
#define PTL2_TYPE_BLOCK		(1 << 0)

/*
 * Block
 */
#define PTL2_MEMTYPE(x)		((x) << 2)
#define PTL2_BLOCK_NON_SHARE	(0 << 8)
#define PTL2_BLOCK_OUTER_SHARE	(2 << 8)
#define PTL2_BLOCK_INNER_SHARE	(3 << 8)
#define PTL2_BLOCK_AF		(1 << 10)
#define PTL2_BLOCK_NG		(1 << 11)
#define PTL2_BLOCK_PXN		(UL(1) << 53)
#define PTL2_BLOCK_UXN		(UL(1) << 54)

#else
/*
 * Level 2 descriptor (PMD).
 */
#define PMD_TYPE_MASK		(3 << 0)
#define PMD_TYPE_FAULT		(0 << 0)
#define PMD_TYPE_TABLE		(3 << 0)
#define PMD_TYPE_SECT		(1 << 0)

/*
 * Section
 */
#define PMD_SECT_NS		(1 << 5)
#define PMD_SECT_NON_SHARE	(0 << 8)
#define PMD_SECT_OUTER_SHARE	(2 << 8)
#define PMD_SECT_INNER_SHARE	(3 << 8)
#define PMD_SECT_AF		(1 << 10)
#define PMD_SECT_NG		(1 << 11)
#define PMD_SECT_PXN		(UL(1) << 53)
#define PMD_SECT_UXN		(UL(1) << 54)

#endif

/*
 * AttrIndx[2:0]
 */
#define PMD_ATTRINDX(t)		((t) << 2)
#define PMD_ATTRINDX_MASK	(7 << 2)

/*
 * TCR flags.
 */
#define TCR_T0SZ(x)		((64 - (x)) << 0)
#define TCR_IRGN_NC		(0 << 8)
#define TCR_IRGN_WBWA		(1 << 8)
#define TCR_IRGN_WT		(2 << 8)
#define TCR_IRGN_WBNWA		(3 << 8)
#define TCR_IRGN_MASK		(3 << 8)
#define TCR_ORGN_NC		(0 << 10)
#define TCR_ORGN_WBWA		(1 << 10)
#define TCR_ORGN_WT		(2 << 10)
#define TCR_ORGN_WBNWA		(3 << 10)
#define TCR_ORGN_MASK		(3 << 10)
#define TCR_SHARED_NON		(0 << 12)
#define TCR_SHARED_OUTER	(2 << 12)
#define TCR_SHARED_INNER	(3 << 12)
#define TCR_TG0_4K		(0 << 14)
#define TCR_TG0_64K		(1 << 14)
#define TCR_TG0_16K		(2 << 14)

#ifndef CONFIG_SYS_FULL_VA
#define TCR_EL1_IPS_BITS	(UL(3) << 32)	/* 42 bits physical address */
#define TCR_EL2_IPS_BITS	(3 << 16)	/* 42 bits physical address */
#define TCR_EL3_IPS_BITS	(3 << 16)	/* 42 bits physical address */

/* PTWs cacheable, inner/outer WBWA and inner shareable */
#define TCR_FLAGS		(TCR_TG0_64K |		\
				TCR_SHARED_INNER |	\
				TCR_ORGN_WBWA |		\
				TCR_IRGN_WBWA |		\
				TCR_T0SZ(VA_BITS))
#endif

#define TCR_EL1_RSVD		(1 << 31)
#define TCR_EL2_RSVD		(1 << 31 | 1 << 23)
#define TCR_EL3_RSVD		(1 << 31 | 1 << 23)

#ifndef __ASSEMBLY__
#ifndef CONFIG_SYS_FULL_VA

void set_pgtable_section(u64 *page_table, u64 index,
			 u64 section, u64 memory_type,
			 u64 attribute);
void set_pgtable_table(u64 *page_table, u64 index,
		       u64 *table_addr);

#endif
static inline void set_ttbr_tcr_mair(int el, u64 table, u64 tcr, u64 attr)
{
	asm volatile("dsb sy");
	if (el == 1) {
		asm volatile("msr ttbr0_el1, %0" : : "r" (table) : "memory");
		asm volatile("msr tcr_el1, %0" : : "r" (tcr) : "memory");
		asm volatile("msr mair_el1, %0" : : "r" (attr) : "memory");
	} else if (el == 2) {
		asm volatile("msr ttbr0_el2, %0" : : "r" (table) : "memory");
		asm volatile("msr tcr_el2, %0" : : "r" (tcr) : "memory");
		asm volatile("msr mair_el2, %0" : : "r" (attr) : "memory");
	} else if (el == 3) {
		asm volatile("msr ttbr0_el3, %0" : : "r" (table) : "memory");
		asm volatile("msr tcr_el3, %0" : : "r" (tcr) : "memory");
		asm volatile("msr mair_el3, %0" : : "r" (attr) : "memory");
	} else {
		hang();
	}
	asm volatile("isb");
}

struct mm_region {
	u64 base;
	u64 size;
	u64 attrs;
};
#endif

#endif /* _ASM_ARMV8_MMU_H_ */
OpenPOWER on IntegriCloud