xref: /rk3399_ARM-atf/lib/xlat_tables/aarch64/xlat_tables.c (revision e8719552a243b7e7e0d2fd3401669e68c9519170)
13ca9928dSSoby Mathew /*
23ca9928dSSoby Mathew  * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
33ca9928dSSoby Mathew  *
43ca9928dSSoby Mathew  * Redistribution and use in source and binary forms, with or without
53ca9928dSSoby Mathew  * modification, are permitted provided that the following conditions are met:
63ca9928dSSoby Mathew  *
73ca9928dSSoby Mathew  * Redistributions of source code must retain the above copyright notice, this
83ca9928dSSoby Mathew  * list of conditions and the following disclaimer.
93ca9928dSSoby Mathew  *
103ca9928dSSoby Mathew  * Redistributions in binary form must reproduce the above copyright notice,
113ca9928dSSoby Mathew  * this list of conditions and the following disclaimer in the documentation
123ca9928dSSoby Mathew  * and/or other materials provided with the distribution.
133ca9928dSSoby Mathew  *
143ca9928dSSoby Mathew  * Neither the name of ARM nor the names of its contributors may be used
153ca9928dSSoby Mathew  * to endorse or promote products derived from this software without specific
163ca9928dSSoby Mathew  * prior written permission.
173ca9928dSSoby Mathew  *
183ca9928dSSoby Mathew  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
193ca9928dSSoby Mathew  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203ca9928dSSoby Mathew  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213ca9928dSSoby Mathew  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
223ca9928dSSoby Mathew  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
233ca9928dSSoby Mathew  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
243ca9928dSSoby Mathew  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
253ca9928dSSoby Mathew  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
263ca9928dSSoby Mathew  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
273ca9928dSSoby Mathew  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
283ca9928dSSoby Mathew  * POSSIBILITY OF SUCH DAMAGE.
293ca9928dSSoby Mathew  */
303ca9928dSSoby Mathew 
313ca9928dSSoby Mathew #include <arch.h>
323ca9928dSSoby Mathew #include <arch_helpers.h>
333ca9928dSSoby Mathew #include <assert.h>
343ca9928dSSoby Mathew #include <cassert.h>
353ca9928dSSoby Mathew #include <platform_def.h>
36ed81f3ebSSandrine Bailleux #include <utils.h>
373ca9928dSSoby Mathew #include <xlat_tables.h>
383ca9928dSSoby Mathew #include "../xlat_tables_private.h"
393ca9928dSSoby Mathew 
403ca9928dSSoby Mathew /*
41*e8719552SAntonio Nino Diaz  * Each platform can define the size of the virtual address space, which is
42*e8719552SAntonio Nino Diaz  * defined in ADDR_SPACE_SIZE. TCR.TxSZ is calculated as 64 minus the width of
43*e8719552SAntonio Nino Diaz  * said address space. The value of TCR.TxSZ must be in the range 16 to 39 [1],
44*e8719552SAntonio Nino Diaz  * which means that the virtual address space width must be in the range 48 to
45*e8719552SAntonio Nino Diaz  * 25 bits.
46*e8719552SAntonio Nino Diaz  *
47*e8719552SAntonio Nino Diaz  * Here we calculate the initial lookup level from the value of ADDR_SPACE_SIZE.
48*e8719552SAntonio Nino Diaz  * For a 4 KB page size, level 0 supports virtual address spaces of widths 48 to
49*e8719552SAntonio Nino Diaz  * 40 bits, level 1 from 39 to 31, and level 2 from 30 to 25. Wider or narrower
50*e8719552SAntonio Nino Diaz  * address spaces are not supported. As a result, level 3 cannot be used as
51*e8719552SAntonio Nino Diaz  * initial lookup level with 4 KB granularity. [2]
52*e8719552SAntonio Nino Diaz  *
53*e8719552SAntonio Nino Diaz  * For example, for a 35-bit address space (i.e. ADDR_SPACE_SIZE == 1 << 35),
54*e8719552SAntonio Nino Diaz  * TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table D4-11 in
55*e8719552SAntonio Nino Diaz  * the ARM ARM, the initial lookup level for such an address space is 1.
56*e8719552SAntonio Nino Diaz  *
57*e8719552SAntonio Nino Diaz  * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
58*e8719552SAntonio Nino Diaz  * information:
59*e8719552SAntonio Nino Diaz  * [1] Page 1730: 'Input address size', 'For all translation stages'.
60*e8719552SAntonio Nino Diaz  * [2] Section D4.2.5
613ca9928dSSoby Mathew  */
623ca9928dSSoby Mathew 
63*e8719552SAntonio Nino Diaz #if ADDR_SPACE_SIZE > (1ULL << (64 - TCR_TxSZ_MIN))
643ca9928dSSoby Mathew 
65*e8719552SAntonio Nino Diaz # error "ADDR_SPACE_SIZE is too big."
66*e8719552SAntonio Nino Diaz 
67*e8719552SAntonio Nino Diaz #elif ADDR_SPACE_SIZE > (1ULL << L0_XLAT_ADDRESS_SHIFT)
68*e8719552SAntonio Nino Diaz 
69*e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE	0
70*e8719552SAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES	(ADDR_SPACE_SIZE >> L0_XLAT_ADDRESS_SHIFT)
71*e8719552SAntonio Nino Diaz 
72*e8719552SAntonio Nino Diaz #elif ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT)
73*e8719552SAntonio Nino Diaz 
74*e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE	1
75*e8719552SAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES	(ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
76*e8719552SAntonio Nino Diaz 
77*e8719552SAntonio Nino Diaz #elif ADDR_SPACE_SIZE >= (1 << (64 - TCR_TxSZ_MAX))
78*e8719552SAntonio Nino Diaz 
79*e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE	2
80*e8719552SAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES	(ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT)
81*e8719552SAntonio Nino Diaz 
82*e8719552SAntonio Nino Diaz #else
83*e8719552SAntonio Nino Diaz 
84*e8719552SAntonio Nino Diaz # error "ADDR_SPACE_SIZE is too small."
85*e8719552SAntonio Nino Diaz 
86*e8719552SAntonio Nino Diaz #endif
87*e8719552SAntonio Nino Diaz 
88*e8719552SAntonio Nino Diaz static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES]
89*e8719552SAntonio Nino Diaz 		__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
903ca9928dSSoby Mathew 
913ca9928dSSoby Mathew static unsigned long long tcr_ps_bits;
923ca9928dSSoby Mathew 
933ca9928dSSoby Mathew static unsigned long long calc_physical_addr_size_bits(
943ca9928dSSoby Mathew 					unsigned long long max_addr)
953ca9928dSSoby Mathew {
963ca9928dSSoby Mathew 	/* Physical address can't exceed 48 bits */
973ca9928dSSoby Mathew 	assert((max_addr & ADDR_MASK_48_TO_63) == 0);
983ca9928dSSoby Mathew 
993ca9928dSSoby Mathew 	/* 48 bits address */
1003ca9928dSSoby Mathew 	if (max_addr & ADDR_MASK_44_TO_47)
1013ca9928dSSoby Mathew 		return TCR_PS_BITS_256TB;
1023ca9928dSSoby Mathew 
1033ca9928dSSoby Mathew 	/* 44 bits address */
1043ca9928dSSoby Mathew 	if (max_addr & ADDR_MASK_42_TO_43)
1053ca9928dSSoby Mathew 		return TCR_PS_BITS_16TB;
1063ca9928dSSoby Mathew 
1073ca9928dSSoby Mathew 	/* 42 bits address */
1083ca9928dSSoby Mathew 	if (max_addr & ADDR_MASK_40_TO_41)
1093ca9928dSSoby Mathew 		return TCR_PS_BITS_4TB;
1103ca9928dSSoby Mathew 
1113ca9928dSSoby Mathew 	/* 40 bits address */
1123ca9928dSSoby Mathew 	if (max_addr & ADDR_MASK_36_TO_39)
1133ca9928dSSoby Mathew 		return TCR_PS_BITS_1TB;
1143ca9928dSSoby Mathew 
1153ca9928dSSoby Mathew 	/* 36 bits address */
1163ca9928dSSoby Mathew 	if (max_addr & ADDR_MASK_32_TO_35)
1173ca9928dSSoby Mathew 		return TCR_PS_BITS_64GB;
1183ca9928dSSoby Mathew 
1193ca9928dSSoby Mathew 	return TCR_PS_BITS_4GB;
1203ca9928dSSoby Mathew }
1213ca9928dSSoby Mathew 
1223ca9928dSSoby Mathew void init_xlat_tables(void)
1233ca9928dSSoby Mathew {
1243ca9928dSSoby Mathew 	unsigned long long max_pa;
1253ca9928dSSoby Mathew 	uintptr_t max_va;
1263ca9928dSSoby Mathew 	print_mmap();
127*e8719552SAntonio Nino Diaz 	init_xlation_table(0, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
128*e8719552SAntonio Nino Diaz 			   &max_va, &max_pa);
1293ca9928dSSoby Mathew 	tcr_ps_bits = calc_physical_addr_size_bits(max_pa);
1303ca9928dSSoby Mathew 	assert(max_va < ADDR_SPACE_SIZE);
1313ca9928dSSoby Mathew }
1323ca9928dSSoby Mathew 
1333ca9928dSSoby Mathew /*******************************************************************************
1343ca9928dSSoby Mathew  * Macro generating the code for the function enabling the MMU in the given
1353ca9928dSSoby Mathew  * exception level, assuming that the pagetables have already been created.
1363ca9928dSSoby Mathew  *
1373ca9928dSSoby Mathew  *   _el:		Exception level at which the function will run
1383ca9928dSSoby Mathew  *   _tcr_extra:	Extra bits to set in the TCR register. This mask will
1393ca9928dSSoby Mathew  *			be OR'ed with the default TCR value.
1403ca9928dSSoby Mathew  *   _tlbi_fct:		Function to invalidate the TLBs at the current
1413ca9928dSSoby Mathew  *			exception level
1423ca9928dSSoby Mathew  ******************************************************************************/
1433ca9928dSSoby Mathew #define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct)		\
1443ca9928dSSoby Mathew 	void enable_mmu_el##_el(unsigned int flags)				\
1453ca9928dSSoby Mathew 	{								\
1463ca9928dSSoby Mathew 		uint64_t mair, tcr, ttbr;				\
1473ca9928dSSoby Mathew 		uint32_t sctlr;						\
1483ca9928dSSoby Mathew 									\
1493ca9928dSSoby Mathew 		assert(IS_IN_EL(_el));					\
1503ca9928dSSoby Mathew 		assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0);	\
1513ca9928dSSoby Mathew 									\
1523ca9928dSSoby Mathew 		/* Set attributes in the right indices of the MAIR */	\
1533ca9928dSSoby Mathew 		mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);	\
1543ca9928dSSoby Mathew 		mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,		\
1553ca9928dSSoby Mathew 				ATTR_IWBWA_OWBWA_NTR_INDEX);		\
1563ca9928dSSoby Mathew 		mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE,		\
1573ca9928dSSoby Mathew 				ATTR_NON_CACHEABLE_INDEX);		\
1583ca9928dSSoby Mathew 		write_mair_el##_el(mair);				\
1593ca9928dSSoby Mathew 									\
1603ca9928dSSoby Mathew 		/* Invalidate TLBs at the current exception level */	\
1613ca9928dSSoby Mathew 		_tlbi_fct();						\
1623ca9928dSSoby Mathew 									\
1633ca9928dSSoby Mathew 		/* Set TCR bits as well. */				\
164*e8719552SAntonio Nino Diaz 		/* Inner & outer WBWA & shareable. */			\
165*e8719552SAntonio Nino Diaz 		/* Set T0SZ to (64 - width of virtual address space) */	\
1663ca9928dSSoby Mathew 		tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |	\
1673ca9928dSSoby Mathew 			TCR_RGN_INNER_WBA |				\
1683ca9928dSSoby Mathew 			(64 - __builtin_ctzl(ADDR_SPACE_SIZE));		\
1693ca9928dSSoby Mathew 		tcr |= _tcr_extra;					\
1703ca9928dSSoby Mathew 		write_tcr_el##_el(tcr);					\
1713ca9928dSSoby Mathew 									\
1723ca9928dSSoby Mathew 		/* Set TTBR bits as well */				\
173*e8719552SAntonio Nino Diaz 		ttbr = (uint64_t) base_xlation_table;			\
1743ca9928dSSoby Mathew 		write_ttbr0_el##_el(ttbr);				\
1753ca9928dSSoby Mathew 									\
1763ca9928dSSoby Mathew 		/* Ensure all translation table writes have drained */	\
1773ca9928dSSoby Mathew 		/* into memory, the TLB invalidation is complete, */	\
1783ca9928dSSoby Mathew 		/* and translation register writes are committed */	\
1793ca9928dSSoby Mathew 		/* before enabling the MMU */				\
1803ca9928dSSoby Mathew 		dsb();							\
1813ca9928dSSoby Mathew 		isb();							\
1823ca9928dSSoby Mathew 									\
1833ca9928dSSoby Mathew 		sctlr = read_sctlr_el##_el();				\
1843ca9928dSSoby Mathew 		sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;			\
1853ca9928dSSoby Mathew 									\
1863ca9928dSSoby Mathew 		if (flags & DISABLE_DCACHE)				\
1873ca9928dSSoby Mathew 			sctlr &= ~SCTLR_C_BIT;				\
1883ca9928dSSoby Mathew 		else							\
1893ca9928dSSoby Mathew 			sctlr |= SCTLR_C_BIT;				\
1903ca9928dSSoby Mathew 									\
1913ca9928dSSoby Mathew 		write_sctlr_el##_el(sctlr);				\
1923ca9928dSSoby Mathew 									\
1933ca9928dSSoby Mathew 		/* Ensure the MMU enable takes effect immediately */	\
1943ca9928dSSoby Mathew 		isb();							\
1953ca9928dSSoby Mathew 	}
1963ca9928dSSoby Mathew 
1973ca9928dSSoby Mathew /* Define EL1 and EL3 variants of the function enabling the MMU */
1983ca9928dSSoby Mathew DEFINE_ENABLE_MMU_EL(1,
1993ca9928dSSoby Mathew 		(tcr_ps_bits << TCR_EL1_IPS_SHIFT),
2003ca9928dSSoby Mathew 		tlbivmalle1)
2013ca9928dSSoby Mathew DEFINE_ENABLE_MMU_EL(3,
2023ca9928dSSoby Mathew 		TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT),
2033ca9928dSSoby Mathew 		tlbialle3)
204