13ca9928dSSoby Mathew /* 25d21b037SSummer Qin * Copyright (c) 2014-2017, 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> 340029624fSAntonio Nino Diaz #include <bl_common.h> 353ca9928dSSoby Mathew #include <cassert.h> 360029624fSAntonio Nino Diaz #include <common_def.h> 373ca9928dSSoby Mathew #include <platform_def.h> 380029624fSAntonio Nino Diaz #include <sys/types.h> 39ed81f3ebSSandrine Bailleux #include <utils.h> 403ca9928dSSoby Mathew #include <xlat_tables.h> 413ca9928dSSoby Mathew #include "../xlat_tables_private.h" 423ca9928dSSoby Mathew 433ca9928dSSoby Mathew /* 44e8719552SAntonio Nino Diaz * Each platform can define the size of the virtual address space, which is 450029624fSAntonio Nino Diaz * defined in PLAT_VIRT_ADDR_SPACE_SIZE. TCR.TxSZ is calculated as 64 minus the 460029624fSAntonio Nino Diaz * width of said address space. The value of TCR.TxSZ must be in the range 16 470029624fSAntonio Nino Diaz * to 39 [1], which means that the virtual address space width must be in the 480029624fSAntonio Nino Diaz * range 48 to 25 bits. 49e8719552SAntonio Nino Diaz * 500029624fSAntonio Nino Diaz * Here we calculate the initial lookup level from the value of 510029624fSAntonio Nino Diaz * PLAT_VIRT_ADDR_SPACE_SIZE. For a 4 KB page size, level 0 supports virtual 520029624fSAntonio Nino Diaz * address spaces of widths 48 to 40 bits, level 1 from 39 to 31, and level 2 530029624fSAntonio Nino Diaz * from 30 to 25. Wider or narrower address spaces are not supported. As a 540029624fSAntonio Nino Diaz * result, level 3 cannot be used as initial lookup level with 4 KB 550029624fSAntonio Nino Diaz * granularity. [2] 56e8719552SAntonio Nino Diaz * 570029624fSAntonio Nino Diaz * For example, for a 35-bit address space (i.e. PLAT_VIRT_ADDR_SPACE_SIZE == 580029624fSAntonio Nino Diaz * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table 590029624fSAntonio Nino Diaz * D4-11 in the ARM ARM, the initial lookup level for an address space like 600029624fSAntonio Nino Diaz * that is 1. 61e8719552SAntonio Nino Diaz * 62e8719552SAntonio Nino Diaz * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more 63e8719552SAntonio Nino Diaz * information: 64e8719552SAntonio Nino Diaz * [1] Page 1730: 'Input address size', 'For all translation stages'. 65e8719552SAntonio Nino Diaz * [2] Section D4.2.5 663ca9928dSSoby Mathew */ 673ca9928dSSoby Mathew 680029624fSAntonio Nino Diaz #if PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << (64 - TCR_TxSZ_MIN)) 693ca9928dSSoby Mathew 700029624fSAntonio Nino Diaz # error "PLAT_VIRT_ADDR_SPACE_SIZE is too big." 71e8719552SAntonio Nino Diaz 720029624fSAntonio Nino Diaz #elif PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << L0_XLAT_ADDRESS_SHIFT) 73e8719552SAntonio Nino Diaz 74e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE 0 750029624fSAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES \ 760029624fSAntonio Nino Diaz (PLAT_VIRT_ADDR_SPACE_SIZE >> L0_XLAT_ADDRESS_SHIFT) 77e8719552SAntonio Nino Diaz 780029624fSAntonio Nino Diaz #elif PLAT_VIRT_ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT) 79e8719552SAntonio Nino Diaz 80e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE 1 810029624fSAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES \ 820029624fSAntonio Nino Diaz (PLAT_VIRT_ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT) 83e8719552SAntonio Nino Diaz 840029624fSAntonio Nino Diaz #elif PLAT_VIRT_ADDR_SPACE_SIZE >= (1 << (64 - TCR_TxSZ_MAX)) 85e8719552SAntonio Nino Diaz 86e8719552SAntonio Nino Diaz # define XLAT_TABLE_LEVEL_BASE 2 870029624fSAntonio Nino Diaz # define NUM_BASE_LEVEL_ENTRIES \ 880029624fSAntonio Nino Diaz (PLAT_VIRT_ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT) 89e8719552SAntonio Nino Diaz 90e8719552SAntonio Nino Diaz #else 91e8719552SAntonio Nino Diaz 920029624fSAntonio Nino Diaz # error "PLAT_VIRT_ADDR_SPACE_SIZE is too small." 93e8719552SAntonio Nino Diaz 94e8719552SAntonio Nino Diaz #endif 95e8719552SAntonio Nino Diaz 96e8719552SAntonio Nino Diaz static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES] 97e8719552SAntonio Nino Diaz __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); 983ca9928dSSoby Mathew 993ca9928dSSoby Mathew static unsigned long long tcr_ps_bits; 1003ca9928dSSoby Mathew 1013ca9928dSSoby Mathew static unsigned long long calc_physical_addr_size_bits( 1023ca9928dSSoby Mathew unsigned long long max_addr) 1033ca9928dSSoby Mathew { 1043ca9928dSSoby Mathew /* Physical address can't exceed 48 bits */ 1053ca9928dSSoby Mathew assert((max_addr & ADDR_MASK_48_TO_63) == 0); 1063ca9928dSSoby Mathew 1073ca9928dSSoby Mathew /* 48 bits address */ 1083ca9928dSSoby Mathew if (max_addr & ADDR_MASK_44_TO_47) 1093ca9928dSSoby Mathew return TCR_PS_BITS_256TB; 1103ca9928dSSoby Mathew 1113ca9928dSSoby Mathew /* 44 bits address */ 1123ca9928dSSoby Mathew if (max_addr & ADDR_MASK_42_TO_43) 1133ca9928dSSoby Mathew return TCR_PS_BITS_16TB; 1143ca9928dSSoby Mathew 1153ca9928dSSoby Mathew /* 42 bits address */ 1163ca9928dSSoby Mathew if (max_addr & ADDR_MASK_40_TO_41) 1173ca9928dSSoby Mathew return TCR_PS_BITS_4TB; 1183ca9928dSSoby Mathew 1193ca9928dSSoby Mathew /* 40 bits address */ 1203ca9928dSSoby Mathew if (max_addr & ADDR_MASK_36_TO_39) 1213ca9928dSSoby Mathew return TCR_PS_BITS_1TB; 1223ca9928dSSoby Mathew 1233ca9928dSSoby Mathew /* 36 bits address */ 1243ca9928dSSoby Mathew if (max_addr & ADDR_MASK_32_TO_35) 1253ca9928dSSoby Mathew return TCR_PS_BITS_64GB; 1263ca9928dSSoby Mathew 1273ca9928dSSoby Mathew return TCR_PS_BITS_4GB; 1283ca9928dSSoby Mathew } 1293ca9928dSSoby Mathew 130aa61368eSAntonio Nino Diaz #if ENABLE_ASSERTIONS 1310029624fSAntonio Nino Diaz /* Physical Address ranges supported in the AArch64 Memory Model */ 1320029624fSAntonio Nino Diaz static const unsigned int pa_range_bits_arr[] = { 1330029624fSAntonio Nino Diaz PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, 1340029624fSAntonio Nino Diaz PARANGE_0101 1350029624fSAntonio Nino Diaz }; 1360029624fSAntonio Nino Diaz 1370029624fSAntonio Nino Diaz static unsigned long long get_max_supported_pa(void) 1380029624fSAntonio Nino Diaz { 1390029624fSAntonio Nino Diaz u_register_t pa_range = read_id_aa64mmfr0_el1() & 1400029624fSAntonio Nino Diaz ID_AA64MMFR0_EL1_PARANGE_MASK; 1410029624fSAntonio Nino Diaz 1420029624fSAntonio Nino Diaz /* All other values are reserved */ 1430029624fSAntonio Nino Diaz assert(pa_range < ARRAY_SIZE(pa_range_bits_arr)); 1440029624fSAntonio Nino Diaz 1450029624fSAntonio Nino Diaz return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL; 1460029624fSAntonio Nino Diaz } 147aa61368eSAntonio Nino Diaz #endif /* ENABLE_ASSERTIONS */ 1480029624fSAntonio Nino Diaz 149*a5640252SAntonio Nino Diaz int xlat_arch_current_el(void) 150*a5640252SAntonio Nino Diaz { 151*a5640252SAntonio Nino Diaz int el = GET_EL(read_CurrentEl()); 152*a5640252SAntonio Nino Diaz 153*a5640252SAntonio Nino Diaz assert(el > 0); 154*a5640252SAntonio Nino Diaz 155*a5640252SAntonio Nino Diaz return el; 156*a5640252SAntonio Nino Diaz } 157*a5640252SAntonio Nino Diaz 158*a5640252SAntonio Nino Diaz uint64_t xlat_arch_get_xn_desc(int el) 159*a5640252SAntonio Nino Diaz { 160*a5640252SAntonio Nino Diaz if (el == 3) { 161*a5640252SAntonio Nino Diaz return UPPER_ATTRS(XN); 162*a5640252SAntonio Nino Diaz } else { 163*a5640252SAntonio Nino Diaz assert(el == 1); 164*a5640252SAntonio Nino Diaz return UPPER_ATTRS(PXN); 165*a5640252SAntonio Nino Diaz } 166*a5640252SAntonio Nino Diaz } 167*a5640252SAntonio Nino Diaz 1683ca9928dSSoby Mathew void init_xlat_tables(void) 1693ca9928dSSoby Mathew { 1703ca9928dSSoby Mathew unsigned long long max_pa; 1713ca9928dSSoby Mathew uintptr_t max_va; 1723ca9928dSSoby Mathew print_mmap(); 173e8719552SAntonio Nino Diaz init_xlation_table(0, base_xlation_table, XLAT_TABLE_LEVEL_BASE, 174e8719552SAntonio Nino Diaz &max_va, &max_pa); 1750029624fSAntonio Nino Diaz 1760029624fSAntonio Nino Diaz assert(max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1); 1770029624fSAntonio Nino Diaz assert(max_pa <= PLAT_PHY_ADDR_SPACE_SIZE - 1); 1780029624fSAntonio Nino Diaz assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <= get_max_supported_pa()); 1790029624fSAntonio Nino Diaz 1803ca9928dSSoby Mathew tcr_ps_bits = calc_physical_addr_size_bits(max_pa); 1813ca9928dSSoby Mathew } 1823ca9928dSSoby Mathew 1833ca9928dSSoby Mathew /******************************************************************************* 1843ca9928dSSoby Mathew * Macro generating the code for the function enabling the MMU in the given 1853ca9928dSSoby Mathew * exception level, assuming that the pagetables have already been created. 1863ca9928dSSoby Mathew * 1873ca9928dSSoby Mathew * _el: Exception level at which the function will run 1883ca9928dSSoby Mathew * _tcr_extra: Extra bits to set in the TCR register. This mask will 1893ca9928dSSoby Mathew * be OR'ed with the default TCR value. 1903ca9928dSSoby Mathew * _tlbi_fct: Function to invalidate the TLBs at the current 1913ca9928dSSoby Mathew * exception level 1923ca9928dSSoby Mathew ******************************************************************************/ 1933ca9928dSSoby Mathew #define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct) \ 1943ca9928dSSoby Mathew void enable_mmu_el##_el(unsigned int flags) \ 1953ca9928dSSoby Mathew { \ 1963ca9928dSSoby Mathew uint64_t mair, tcr, ttbr; \ 1973ca9928dSSoby Mathew uint32_t sctlr; \ 1983ca9928dSSoby Mathew \ 1993ca9928dSSoby Mathew assert(IS_IN_EL(_el)); \ 2003ca9928dSSoby Mathew assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0); \ 2013ca9928dSSoby Mathew \ 2023ca9928dSSoby Mathew /* Set attributes in the right indices of the MAIR */ \ 2033ca9928dSSoby Mathew mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); \ 2043ca9928dSSoby Mathew mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, \ 2053ca9928dSSoby Mathew ATTR_IWBWA_OWBWA_NTR_INDEX); \ 2063ca9928dSSoby Mathew mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, \ 2073ca9928dSSoby Mathew ATTR_NON_CACHEABLE_INDEX); \ 2083ca9928dSSoby Mathew write_mair_el##_el(mair); \ 2093ca9928dSSoby Mathew \ 2103ca9928dSSoby Mathew /* Invalidate TLBs at the current exception level */ \ 2113ca9928dSSoby Mathew _tlbi_fct(); \ 2123ca9928dSSoby Mathew \ 2133ca9928dSSoby Mathew /* Set TCR bits as well. */ \ 214e8719552SAntonio Nino Diaz /* Set T0SZ to (64 - width of virtual address space) */ \ 2155d21b037SSummer Qin if (flags & XLAT_TABLE_NC) { \ 2165d21b037SSummer Qin /* Inner & outer non-cacheable non-shareable. */\ 2175d21b037SSummer Qin tcr = TCR_SH_NON_SHAREABLE | \ 2185d21b037SSummer Qin TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC | \ 2190029624fSAntonio Nino Diaz (64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\ 2205d21b037SSummer Qin } else { \ 2215d21b037SSummer Qin /* Inner & outer WBWA & shareable. */ \ 2225d21b037SSummer Qin tcr = TCR_SH_INNER_SHAREABLE | \ 2235d21b037SSummer Qin TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA | \ 2245d21b037SSummer Qin (64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\ 2255d21b037SSummer Qin } \ 2263ca9928dSSoby Mathew tcr |= _tcr_extra; \ 2273ca9928dSSoby Mathew write_tcr_el##_el(tcr); \ 2283ca9928dSSoby Mathew \ 2293ca9928dSSoby Mathew /* Set TTBR bits as well */ \ 230e8719552SAntonio Nino Diaz ttbr = (uint64_t) base_xlation_table; \ 2313ca9928dSSoby Mathew write_ttbr0_el##_el(ttbr); \ 2323ca9928dSSoby Mathew \ 2333ca9928dSSoby Mathew /* Ensure all translation table writes have drained */ \ 2343ca9928dSSoby Mathew /* into memory, the TLB invalidation is complete, */ \ 2353ca9928dSSoby Mathew /* and translation register writes are committed */ \ 2363ca9928dSSoby Mathew /* before enabling the MMU */ \ 237ccbec91cSAntonio Nino Diaz dsbish(); \ 2383ca9928dSSoby Mathew isb(); \ 2393ca9928dSSoby Mathew \ 2403ca9928dSSoby Mathew sctlr = read_sctlr_el##_el(); \ 2413ca9928dSSoby Mathew sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; \ 2423ca9928dSSoby Mathew \ 2433ca9928dSSoby Mathew if (flags & DISABLE_DCACHE) \ 2443ca9928dSSoby Mathew sctlr &= ~SCTLR_C_BIT; \ 2453ca9928dSSoby Mathew else \ 2463ca9928dSSoby Mathew sctlr |= SCTLR_C_BIT; \ 2473ca9928dSSoby Mathew \ 2483ca9928dSSoby Mathew write_sctlr_el##_el(sctlr); \ 2493ca9928dSSoby Mathew \ 2503ca9928dSSoby Mathew /* Ensure the MMU enable takes effect immediately */ \ 2513ca9928dSSoby Mathew isb(); \ 2523ca9928dSSoby Mathew } 2533ca9928dSSoby Mathew 2543ca9928dSSoby Mathew /* Define EL1 and EL3 variants of the function enabling the MMU */ 2553ca9928dSSoby Mathew DEFINE_ENABLE_MMU_EL(1, 2563ca9928dSSoby Mathew (tcr_ps_bits << TCR_EL1_IPS_SHIFT), 2573ca9928dSSoby Mathew tlbivmalle1) 2583ca9928dSSoby Mathew DEFINE_ENABLE_MMU_EL(3, 2593ca9928dSSoby Mathew TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT), 2603ca9928dSSoby Mathew tlbialle3) 261