]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
Calculate TCR bits based on VA and PA
authorLin Ma <lin.ma@caviumnetworks.com>
Fri, 27 Jun 2014 23:56:30 +0000 (16:56 -0700)
committerDan Handley <dan.handley@arm.com>
Wed, 9 Jul 2014 11:33:33 +0000 (12:33 +0100)
Currently the TCR bits are hardcoded in xlat_tables.c. In order to
map higher physical address into low virtual address, the TCR bits
need to be configured accordingly.

This patch is to save the max VA and PA and calculate the TCR.PS/IPS
and t0sz bits in init_xlat_tables function.

Change-Id: Ia7a58e5372b20200153057d457f4be5ddbb7dae4

include/lib/aarch64/arch.h
lib/aarch64/xlat_tables.c

index 5dc488bb1c57ff2f6196f5372a803ec8759f3777..ff91efc41ad2499bb50d8e3aeaae7888b5f780de 100644 (file)
  * TCR defintions
  */
 #define TCR_EL3_RES1           ((1UL << 31) | (1UL << 23))
-
-#define TCR_T0SZ_4GB           32
+#define TCR_EL1_IPS_SHIFT      32
+#define TCR_EL3_PS_SHIFT       16
+
+/* (internal) physical address size bits in EL3/EL1 */
+#define TCR_PS_BITS_4GB                (0x0)
+#define TCR_PS_BITS_64GB       (0x1)
+#define TCR_PS_BITS_1TB                (0x2)
+#define TCR_PS_BITS_4TB                (0x3)
+#define TCR_PS_BITS_16TB       (0x4)
+#define TCR_PS_BITS_256TB      (0x5)
+
+#define ADDR_MASK_48_TO_63     0xFFFF000000000000UL
+#define ADDR_MASK_44_TO_47     0x0000F00000000000UL
+#define ADDR_MASK_42_TO_43     0x00000C0000000000UL
+#define ADDR_MASK_40_TO_41     0x0000030000000000UL
+#define ADDR_MASK_36_TO_39     0x000000F000000000UL
+#define ADDR_MASK_32_TO_35     0x0000000F00000000UL
 
 #define TCR_RGN_INNER_NC       (0x0 << 8)
 #define TCR_RGN_INNER_WBA      (0x1 << 8)
index 1b99cc85feba3ed2f8446886cbb2d8ab6e8b0a47..f1d658d528b572c717da23be3102f8d1a78c232f 100644 (file)
@@ -31,6 +31,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
+#include <cassert.h>
 #include <platform_def.h>
 #include <string.h>
 #include <xlat_tables.h>
@@ -46,6 +47,7 @@
 #define debug_print(...) ((void)0)
 #endif
 
+CASSERT(ADDR_SPACE_SIZE > 0, assert_valid_addr_space_size);
 
 #define UNSET_DESC     ~0ul
 
@@ -58,6 +60,9 @@ static uint64_t xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES]
 __aligned(XLAT_TABLE_SIZE) __attribute__((section("xlat_table")));
 
 static unsigned next_xlat;
+static unsigned long max_pa;
+static unsigned long max_va;
+static unsigned long tcr_ps_bits;
 
 /*
  * Array of all memory regions stored in order of ascending base address.
@@ -85,6 +90,8 @@ void mmap_add_region(unsigned long base_pa, unsigned long base_va,
 {
        mmap_region_t *mm = mmap;
        mmap_region_t *mm_last = mm + sizeof(mmap) / sizeof(mmap[0]) - 1;
+       unsigned long pa_end = base_pa + size - 1;
+       unsigned long va_end = base_va + size - 1;
 
        assert(IS_PAGE_ALIGNED(base_pa));
        assert(IS_PAGE_ALIGNED(base_va));
@@ -107,6 +114,11 @@ void mmap_add_region(unsigned long base_pa, unsigned long base_va,
        mm->base_va = base_va;
        mm->size = size;
        mm->attr = attr;
+
+       if (pa_end > max_pa)
+               max_pa = pa_end;
+       if (va_end > max_va)
+               max_va = va_end;
 }
 
 void mmap_add(const mmap_region_t *mm)
@@ -233,10 +245,40 @@ static mmap_region_t *init_xlation_table(mmap_region_t *mm,
        return mm;
 }
 
+static unsigned int calc_physical_addr_size_bits(unsigned long max_addr)
+{
+       /* Physical address can't exceed 48 bits */
+       assert((max_addr & ADDR_MASK_48_TO_63) == 0);
+
+       /* 48 bits address */
+       if (max_addr & ADDR_MASK_44_TO_47)
+               return TCR_PS_BITS_256TB;
+
+       /* 44 bits address */
+       if (max_addr & ADDR_MASK_42_TO_43)
+               return TCR_PS_BITS_16TB;
+
+       /* 42 bits address */
+       if (max_addr & ADDR_MASK_40_TO_41)
+               return TCR_PS_BITS_4TB;
+
+       /* 40 bits address */
+       if (max_addr & ADDR_MASK_36_TO_39)
+               return TCR_PS_BITS_1TB;
+
+       /* 36 bits address */
+       if (max_addr & ADDR_MASK_32_TO_35)
+               return TCR_PS_BITS_64GB;
+
+       return TCR_PS_BITS_4GB;
+}
+
 void init_xlat_tables(void)
 {
        print_mmap();
        init_xlation_table(mmap, 0, l1_xlation_table, 1);
+       tcr_ps_bits = calc_physical_addr_size_bits(max_pa);
+       assert(max_va < ADDR_SPACE_SIZE);
 }
 
 /*******************************************************************************
@@ -270,7 +312,8 @@ void init_xlat_tables(void)
                /* Set TCR bits as well. */                             \
                /* Inner & outer WBWA & shareable + T0SZ = 32 */        \
                tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |      \
-                       TCR_RGN_INNER_WBA | TCR_T0SZ_4GB;               \
+                       TCR_RGN_INNER_WBA |                             \
+                       (64 - __builtin_ctzl(ADDR_SPACE_SIZE));         \
                tcr |= _tcr_extra;                                      \
                write_tcr_el##_el(tcr);                                 \
                                                                        \
@@ -295,5 +338,9 @@ void init_xlat_tables(void)
        }
 
 /* Define EL1 and EL3 variants of the function enabling the MMU */
-DEFINE_ENABLE_MMU_EL(1, 0, tlbivmalle1)
-DEFINE_ENABLE_MMU_EL(3, TCR_EL3_RES1, tlbialle3)
+DEFINE_ENABLE_MMU_EL(1,
+               (tcr_ps_bits << TCR_EL1_IPS_SHIFT),
+               tlbivmalle1)
+DEFINE_ENABLE_MMU_EL(3,
+               TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT),
+               tlbialle3)