Pratyush, On 01/12/2016 02:12 PM, Pratyush Anand wrote: > This patch adds support to enable/disable d-cache, which can be used for > faster purgatory sha256 verification. > > We are supporting only 4K and 64K page sizes. This code will not work if a > hardware is not supporting at least one of these page sizes. Therefore, > D-cache is disabled by default and enabled only when "enable-dcache" is > passed to the kexec(). > Since this is an identity mapped system, so VA_BITS will be same as max PA > bits supported. If VA_BITS <= 42 for 64K and <= 39 for 4K then only one > level of page table will be there with block descriptor entries. > Otherwise, For 4K mapping, TTBR points to level 0 lookups, which will have > only table entries pointing to a level 1 lookup. Level 1 will have only > block entries which will map 1GB block. For 64K mapping, TTBR points to > level 1 lookups, which will have only table entries pointing to a level 2 > lookup. Level 2 will have only block entries which will map 512MB block. If > UART base address and RAM addresses are not at least 1GB and 512MB apart > for 4K and 64K respectively, then mapping result could be unpredictable. In > that case we need to support one more level of granularity, but until > someone needs that keep it like this only. > We can not allocate dynamic memory in purgatory. Therefore we keep page > table allocation size fixed as (3 * MAX_PAGE_SIZE). (page_table) points to > first level (having only table entries) and (page_table + MAX_PAGE_SIZE) > points to table at next level (having block entries). If index for RAM > area and UART area in first table is not same, then we will need another > next level table which will be located at (page_table + 2 * MAX_PAGE_SIZE). > > Signed-off-by: Pratyush Anand <panand at redhat.com> > --- > purgatory/arch/arm64/Makefile | 2 + > purgatory/arch/arm64/cache-asm.S | 228 +++++++++++++++++++++++++++ > purgatory/arch/arm64/cache.c | 333 +++++++++++++++++++++++++++++++++++++++ > purgatory/arch/arm64/cache.h | 83 ++++++++++ > 4 files changed, 646 insertions(+) > create mode 100644 purgatory/arch/arm64/cache-asm.S > create mode 100644 purgatory/arch/arm64/cache.c > create mode 100644 purgatory/arch/arm64/cache.h > > diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile > index 636abeab17b2..0f80f8165d90 100644 > --- a/purgatory/arch/arm64/Makefile > +++ b/purgatory/arch/arm64/Makefile > @@ -11,6 +11,8 @@ arm64_PURGATORY_EXTRA_CFLAGS = \ > > arm64_PURGATORY_SRCS += \ > purgatory/arch/arm64/entry.S \ > + purgatory/arch/arm64/cache-asm.S \ > + purgatory/arch/arm64/cache.c \ > purgatory/arch/arm64/purgatory-arm64.c > > dist += \ > diff --git a/purgatory/arch/arm64/cache-asm.S b/purgatory/arch/arm64/cache-asm.S > new file mode 100644 > index 000000000000..8ef4083343f1 > --- /dev/null > +++ b/purgatory/arch/arm64/cache-asm.S > @@ -0,0 +1,228 @@ > +/* > + * Some of the routines have been copied from Linux Kernel, therefore > + * copying the license as well. > + * > + * Copyright (C) 2001 Deep Blue Solutions Ltd. > + * Copyright (C) 2012 ARM Ltd. > + * Copyright (C) 2015 Pratyush Anand <panand at redhat.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "cache.h" > + > +/* > + * dcache_line_size - get the minimum D-cache line size from the CTR register. > + */ > + .macro dcache_line_size, reg, tmp > + mrs \tmp, ctr_el0 // read CTR > + ubfm \tmp, \tmp, #16, #19 // cache line size encoding > + mov \reg, #4 // bytes per word > + lsl \reg, \reg, \tmp // actual cache line size > + .endm > + > +/* > + * inval_cache_range(start, end) > + * - x0 - start - start address of region > + * - x1 - end - end address of region > + */ > +.globl inval_cache_range > +inval_cache_range: > + dcache_line_size x2, x3 > + sub x3, x2, #1 > + tst x1, x3 // end cache line aligned? > + bic x1, x1, x3 > + b.eq 1f > + dc civac, x1 // clean & invalidate D / U line > +1: tst x0, x3 // start cache line aligned? > + bic x0, x0, x3 > + b.eq 2f > + dc civac, x0 // clean & invalidate D / U line > + b 3f > +2: dc ivac, x0 // invalidate D / U line > +3: add x0, x0, x2 > + cmp x0, x1 > + b.lo 2b > + dsb sy > + ret > +/* > + * flush_dcache_range(start, end) > + * - x0 - start - start address of region > + * - x1 - end - end address of region > + * > + */ > +.globl flush_dcache_range > +flush_dcache_range: > + dcache_line_size x2, x3 > + sub x3, x2, #1 > + bic x0, x0, x3 > +1: dc civac, x0 // clean & invalidate D line / unified line > + add x0, x0, x2 > + cmp x0, x1 > + b.lo 1b > + dsb sy > + ret > + > +/* > + * invalidate_tlbs_el1() > + */ > +.globl invalidate_tlbs_el1 > +invalidate_tlbs_el1: > + dsb nshst > + tlbi vmalle1 > + dsb nsh > + isb > + ret > + > +/* > + * invalidate_tlbs_el2() > + */ > +.globl invalidate_tlbs_el2 > +invalidate_tlbs_el2: > + dsb nshst > + tlbi alle2 > + dsb nsh > + isb > + ret > + > +/* > + * invalidate_tlbs_el3() > + */ > +.globl invalidate_tlbs_el3 > +invalidate_tlbs_el3: > + dsb nshst > + tlbi alle3 > + dsb nsh > + isb > + ret > + > +/* > + * get_mm_feature_reg0_val - Get information about supported MM > + * features > + */ > +.globl get_mm_feature_reg0_val > +get_mm_feature_reg0_val: > + mrs x0, ID_AA64MMFR0_EL1 > + ret > + > +/* > + * get_current_el - Get information about current exception level > + */ > +.globl get_current_el > +get_current_el: > + mrs x0, CurrentEL > + lsr x0, x0, #2 > + ret > + > +/* > + * invalidate_icache - Invalidate I-cache > + */ > +.globl invalidate_icache > +invalidate_icache: > + ic iallu > + dsb nsh > + isb > + ret > + > +/* > + * set_mair_tcr_ttbr_sctlr_el1(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers > + * x0 - page_table - Page Table Base > + * x1 - tcr_flags - TCR Flags to be set > + */ > +.globl set_mair_tcr_ttbr_sctlr_el1 > +set_mair_tcr_ttbr_sctlr_el1: > + ldr x2, =MEMORY_ATTRIBUTES > + msr mair_el1, x2 > + msr tcr_el1, x1 > + msr ttbr0_el1, x0 > + isb > + mrs x0, sctlr_el1 > + ldr x3, =SCTLR_ELx_FLAGS > + orr x0, x0, x3 > + msr sctlr_el1, x0 > + isb > + ret > + > +/* > + * set_mair_tcr_ttbr_sctlr_el2(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers > + * x0 - page_table - Page Table Base > + * x1 - tcr_flags - TCR Flags to be set > + */ > +.globl set_mair_tcr_ttbr_sctlr_el2 > +set_mair_tcr_ttbr_sctlr_el2: > + ldr x2, =MEMORY_ATTRIBUTES > + msr mair_el2, x2 > + msr tcr_el2, x1 > + msr ttbr0_el2, x0 > + isb > + mrs x0, sctlr_el2 > + ldr x3, =SCTLR_ELx_FLAGS > + orr x0, x0, x3 > + msr sctlr_el2, x0 > + isb > + ret > + > +/* > + * set_mair_tcr_ttbr_sctlr_el3(page_table, tcr_flags) - sets MAIR, TCR , TTBR and SCTLR registers > + * x0 - page_table - Page Table Base > + * x1 - tcr_flags - TCR Flags to be set > + */ > +.globl set_mair_tcr_ttbr_sctlr_el3 > +set_mair_tcr_ttbr_sctlr_el3: > + ldr x2, =MEMORY_ATTRIBUTES > + msr mair_el3, x2 > + msr tcr_el3, x1 > + msr ttbr0_el3, x0 > + isb > + mrs x0, sctlr_el3 > + ldr x3, =SCTLR_ELx_FLAGS > + orr x0, x0, x3 > + msr sctlr_el3, x0 > + isb > + ret > + > +/* > + * reset_sctlr_el1 - disables cache and mmu > + */ > +.globl reset_sctlr_el1 > +reset_sctlr_el1: > + mrs x0, sctlr_el1 > + bic x0, x0, #SCTLR_ELx_C > + bic x0, x0, #SCTLR_ELx_M > + msr sctlr_el1, x0 > + isb > + ret > + > +/* > + * reset_sctlr_el2 - disables cache and mmu > + */ > +.globl reset_sctlr_el2 > +reset_sctlr_el2: > + mrs x0, sctlr_el2 > + bic x0, x0, #SCTLR_ELx_C > + bic x0, x0, #SCTLR_ELx_M > + msr sctlr_el2, x0 > + isb > + ret > + > +/* > + * reset_sctlr_el3 - disables cache and mmu > + */ > +.globl reset_sctlr_el3 > +reset_sctlr_el3: > + mrs x0, sctlr_el3 > + bic x0, x0, #SCTLR_ELx_C > + bic x0, x0, #SCTLR_ELx_M > + msr sctlr_el3, x0 > + isb > + ret > diff --git a/purgatory/arch/arm64/cache.c b/purgatory/arch/arm64/cache.c > new file mode 100644 > index 000000000000..86f6ab1bb81e > --- /dev/null > +++ b/purgatory/arch/arm64/cache.c > @@ -0,0 +1,333 @@ > +/* > + * Copyright (C) 2015 Pratyush Anand <panand at redhat.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +/* We are supporting only 4K and 64K page sizes. This code will not work if > + * a hardware is not supporting at least one of these page sizes. > + * Therefore, D-cache is disabled by default and enabled only when > + * "enable-dcache" is passed to the kexec(). > + * Since this is an identity mapped system, so VA_BITS will be same as max > + * PA bits supported. If VA_BITS <= 42 for 64K and <= 39 for 4K then only > + * one level of page table will be there with block descriptor entries. > + * Otherwise, For 4K mapping, TTBR points to level 0 lookups, which will > + * have only table entries pointing to a level 1 lookup. Level 1 will have > + * only block entries which will map 1GB block.For 64K mapping, TTBR points > + * to level 1 lookups, which will have only table entries pointing to a > + * level 2 lookup. Level 2 will have only block entries which will map > + * 512MB block. If UART base address and RAM addresses are not at least 1GB > + * and 512MB apart for 4K and 64K respectively, then mapping result could > + * be unpredictable. In that case we need to support one more level of > + * granularity, but until someone needs that keep it like this only. > + * We can not allocate dynamic memory in purgatory. Therefore we keep page > + * table allocation size fixed as (3 * MAX_PAGE_SIZE). (page_table) points > + * to first level (having only table entries) and (page_table + > + * MAX_PAGE_SIZE) points to table at next level (having block entries). If > + * index for RAM area and UART area in first table is not same, then we > + * will need another next level table which will be located at (page_table > + * + 2 * MAX_PAGE_SIZE). > + */ > + > +#include <stdint.h> > +#include <string.h> > +#include <purgatory.h> > +#include "cache.h" > + > +static uint64_t page_shift; > +static uint64_t pgtable_level; > +static uint64_t va_bits; > + > +static uint64_t page_table[PAGE_TABLE_SIZE / sizeof(uint64_t)] __attribute__ ((aligned (MAX_PAGE_SIZE))) = { }; > +static uint64_t page_table_used; > + > +#define PAGE_SIZE (1 << page_shift) > +/* > + * is_4k_page_supported - return true if 4k page is supported else > + * false > + */ > +static int is_4k_page_supported(void) > +{ > + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_TGRAN4_MASK) == > + ID_AA64MMFR0_TGRAN4_SUPPORTED); > +} > + > +/* > + * is_64k_page_supported - return true if 64k page is supported else > + * false > + */ > +static int is_64k_page_supported(void) > +{ > + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_TGRAN64_MASK) == > + ID_AA64MMFR0_TGRAN64_SUPPORTED); > +} > + > +/* > + * get_ips_bits - return supported IPS bits > + */ > +static uint64_t get_ips_bits(void) > +{ > + return ((get_mm_feature_reg0_val() & ID_AA64MMFR0_PARANGE_MASK) >> > + ID_AA64MMFR0_PARANGE_SHIFT); > +} > + > +/* > + * get_va_bits - return supported VA bits (For identity mapping VA = PA) > + */ > +static uint64_t get_va_bits(void) > +{ > + uint64_t ips = get_ips_bits(); > + > + switch(ips) { > + case ID_AA64MMFR0_PARANGE_48: > + return 48; > + case ID_AA64MMFR0_PARANGE_44: > + return 44; > + case ID_AA64MMFR0_PARANGE_42: > + return 42; > + case ID_AA64MMFR0_PARANGE_40: > + return 40; > + case ID_AA64MMFR0_PARANGE_36: > + return 36; > + default: > + return 32; AA64MMFR0_PRANGE_32, instead of 'default', should explicitly be used here as it is defined as 0x0 in ARM ARM. > + } > +} > + > +/* > + * get_section_shift - get block shift for supported page size > + */ > +static uint64_t get_section_shift(void) > +{ > + if (page_shift == 16) > + return 29; > + else if(page_shift == 12) > + return 30; > + else > + return 0; > +} > + > +/* > + * get_section_mask - get section mask for supported page size > + */ > +static uint64_t get_section_mask(void) > +{ > + if (page_shift == 16) > + return 0x1FFF; > + else if(page_shift == 12) > + return 0x1FF; > + else > + return 0; > +} > + > +/* > + * get_pgdir_shift - get pgdir shift for supported page size > + */ > +static uint64_t get_pgdir_shift(void) > +{ > + if (page_shift == 16) > + return 42; > + else if(page_shift == 12) > + return 39; > + else > + return 0; > +} > + > +/* > + * init_page_table - Initializes page table locations > + */ > + > +static void init_page_table(void) > +{ > + inval_cache_range((uint64_t)page_table, > + (uint64_t)page_table + PAGE_TABLE_SIZE); > + memset(page_table, 0, PAGE_TABLE_SIZE); why invalidate first? > +} > +/* > + * create_identity_mapping(start, end, flags) > + * start - start address > + * end - end address > + * flags - MMU Flags for Normal or Device type memory > + */ > +static void create_identity_mapping(uint64_t start, uint64_t end, > + uint64_t flags) > +{ > + uint32_t sec_shift, pgdir_shift, sec_mask; > + uint64_t desc, s1, e1, s2, e2; > + uint64_t *table2; > + > + s1 = start; > + e1 = end; > + > + sec_shift = get_section_shift(); > + if (pgtable_level == 1) { > + s1 >>= sec_shift; > + e1 >>= sec_shift; > + do { > + desc = s1 << sec_shift; > + desc |= flags; > + page_table[s1] = desc; > + s1++; > + } while (s1 <= e1); To be precise, this loop creates an unnecessary entry if 'end' is exclusive. Pls think about the case that end is on sector boundary. Maybe, e1 = (e1 - 1) >> sec_shift > + } else { > + pgdir_shift = get_pgdir_shift(); > + sec_mask = get_section_mask(); > + s1 >>= pgdir_shift; > + e1 >>= pgdir_shift; > + do { > + /* > + * If there is no table entry then write a new > + * entry else, use old entry > + */ > + if (!page_table[s1]) { s1 can be larger than 0, 1 or 2 if ram is located at much higher address than the first (three) sector(s). > + table2 = &page_table[(++page_table_used * > + MAX_PAGE_SIZE) / > + sizeof(uint64_t)]; > + desc = (uint64_t)table2 | PMD_TYPE_TABLE; > + page_table[s1] = desc; > + } else { > + table2 = (uint64_t *)(page_table[s1] & > + ~PMD_TYPE_MASK); > + } > + s1++; > + s2 = start >> sec_shift; > + s2 &= sec_mask; > + e2 = end >> sec_shift; > + e2 &= sec_mask; > + do { > + desc = s2 << sec_shift; > + desc |= flags; > + table2[s2] = desc; > + s2++; > + } while (s2 <= e2); > + } while (s1 <= e1); > + } > +} > + > +/* > + * enable_mmu_dcache: Enable mmu and D-cache in sctlr_el1 > + */ > +static void enable_mmu_dcache(void) > +{ > + uint64_t tcr_flags = TCR_FLAGS | TCR_T0SZ(va_bits); > + > + switch(page_shift) { > + case 16: > + tcr_flags |= TCR_TG0_64K; > + break; > + case 12: > + tcr_flags |= TCR_TG0_4K; > + break; > + default: > + printf("page shift not supported\n"); > + return; > + } > + /* > + * Since the page tables have been populated with non-cacheable > + * accesses (MMU disabled), invalidate the idmap page > + * tables again to remove any speculatively loaded cache lines. > + */ > + inval_cache_range((uint64_t)page_table, > + (uint64_t)page_table + PAGE_TABLE_SIZE); > + > + switch(get_current_el()) { > + case 3: Linux kernel should be started only in EL2 or non-secure EL1. why should we take care of el3? > + invalidate_tlbs_el3(); > + tcr_flags |= (get_ips_bits() << TCR_IPS_EL3_SHIFT); > + set_mair_tcr_ttbr_sctlr_el3((uint64_t)page_table, tcr_flags); > + break; > + case 2: > + invalidate_tlbs_el2(); > + tcr_flags |= (get_ips_bits() << TCR_IPS_EL2_SHIFT); > + set_mair_tcr_ttbr_sctlr_el2((uint64_t)page_table, tcr_flags); > + break; > + case 1: > + invalidate_tlbs_el1(); > + tcr_flags |= (get_ips_bits() << TCR_IPS_EL1_SHIFT); > + set_mair_tcr_ttbr_sctlr_el1((uint64_t)page_table, tcr_flags); > + break; > + default: > + return; > + } > + invalidate_icache(); > +} > + > +/* > + * enable_dcache: Enable D-cache and set appropriate attributes > + * ram_start - Start address of RAM > + * ram_end - End address of RAM > + * uart_base - Base address of uart > + */ > +int enable_dcache(uint64_t ram_start, uint64_t ram_end, uint64_t uart_base) > +{ > + va_bits = get_va_bits(); > + > + page_table_used = 0; > + if (is_64k_page_supported()) { > + page_shift = 16; > + if (va_bits <= 42) > + pgtable_level = 1; > + else > + pgtable_level = 2; > + } else if (is_4k_page_supported()) { > + page_shift = 12; > + if (va_bits <= 39) > + pgtable_level = 1; > + else > + pgtable_level = 2; > + } else { > + printf("Valid Page Granule not supported by hardware\n"); > + return -1; > + } > + init_page_table(); > + create_identity_mapping(ram_start, ram_end, MM_MMUFLAGS_NORMAL); > + printf("Normal identity mapping created from %lx to %lx\n", > + ram_start, ram_end); > + if (uart_base) { > + create_identity_mapping((uint64_t)uart_base, > + (uint64_t)uart_base + PAGE_SIZE, > + MM_MMUFLAGS_DEVICE); > + printf("Device identity mapping created from %lx to %lx\n", > + (uint64_t)uart_base, > + (uint64_t)uart_base + PAGE_SIZE); > + } > + enable_mmu_dcache(); > + printf("Cache Enabled\n"); > + > + return 0; > +} > + > +/* > + * disable_dcache: Disable D-cache and flush RAM locations > + * ram_start - Start address of RAM > + * ram_end - End address of RAM > + */ > +void disable_dcache(uint64_t ram_start, uint64_t ram_end) > +{ > + switch(get_current_el()) { > + case 3: > + reset_sctlr_el3(); > + break; ditto > + case 2: > + reset_sctlr_el2(); > + break; > + case 1: > + reset_sctlr_el1(); > + break; > + default: > + return; > + } > + invalidate_icache(); > + flush_dcache_range(ram_start, ram_end); > + printf("Cache Disabled\n"); > +} > diff --git a/purgatory/arch/arm64/cache.h b/purgatory/arch/arm64/cache.h > new file mode 100644 > index 000000000000..34d779831607 > --- /dev/null > +++ b/purgatory/arch/arm64/cache.h > @@ -0,0 +1,83 @@ > +#ifndef __CACHE_H__ > +#define __CACHE_H__ > + > +#define MT_DEVICE_NGNRNE 0 > +#define MT_DEVICE_NGNRE 1 > +#define MT_DEVICE_GRE 2 > +#define MT_NORMAL_NC 3 > +#define MT_NORMAL 4 > + > +#ifndef __ASSEMBLER__ > + > +#define MAX_PAGE_SIZE 0x10000 > +#define PAGE_TABLE_SIZE (3 * MAX_PAGE_SIZE) > +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 > +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 > +#define ID_AA64MMFR0_TGRAN64_MASK (0xFUL << ID_AA64MMFR0_TGRAN64_SHIFT) > +#define ID_AA64MMFR0_TGRAN4_MASK (0xFUL << ID_AA64MMFR0_TGRAN4_SHIFT) > +#define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0 > +#define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0 > +#define ID_AA64MMFR0_PARANGE_SHIFT 0 > +#define ID_AA64MMFR0_PARANGE_MASK (0xFUL << ID_AA64MMFR0_PARANGE_SHIFT) > +#define ID_AA64MMFR0_PARANGE_48 0x5 > +#define ID_AA64MMFR0_PARANGE_44 0x4 > +#define ID_AA64MMFR0_PARANGE_42 0x3 > +#define ID_AA64MMFR0_PARANGE_40 0x2 > +#define ID_AA64MMFR0_PARANGE_36 0x1 > +#define ID_AA64MMFR0_PARANGE_32 0x0 > + > +#define TCR_TG0_64K (1UL << 14) > +#define TCR_TG0_4K (0UL << 14) > +#define TCR_SHARED_NONE (0UL << 12) > +#define TCR_ORGN_WBWA (1UL << 10) > +#define TCR_IRGN_WBWA (1UL << 8) > +#define TCR_IPS_EL1_SHIFT 32 > +#define TCR_IPS_EL2_SHIFT 16 > +#define TCR_IPS_EL3_SHIFT 16 TCR_PS_EL[23]_SHIFT? Thanks, -Takahiro AKASHI > +#define TCR_T0SZ(x) ((unsigned long)(64 - (x)) << 0) > +#define TCR_FLAGS (TCR_SHARED_NONE | TCR_ORGN_WBWA | TCR_IRGN_WBWA) > + > +#define PMD_TYPE_SECT (1UL << 0) > +#define PMD_TYPE_TABLE (3UL << 0) > +#define PMD_TYPE_MASK 0x3 > +#define PMD_SECT_AF (1UL << 10) > +#define PMD_ATTRINDX(t) ((unsigned long)(t) << 2) > +#define PMD_FLAGS_NORMAL (PMD_TYPE_SECT | PMD_SECT_AF) > +#define PMD_SECT_PXN (1UL << 53) > +#define PMD_SECT_UXN (1UL << 54) > +#define PMD_FLAGS_DEVICE (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_PXN | PMD_SECT_UXN) > +#define MM_MMUFLAGS_NORMAL PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS_NORMAL > +#define MM_MMUFLAGS_DEVICE PMD_ATTRINDX(MT_DEVICE_NGNRE) | PMD_FLAGS_DEVICE > + > +void disable_dcache(uint64_t ram_start, uint64_t ram_end); > +int enable_dcache(uint64_t ram_start, uint64_t ram_end, uint64_t uart_base); > +uint64_t get_mm_feature_reg0_val(void); > +void inval_cache_range(uint64_t start, uint64_t end); > +void flush_dcache_range(uint64_t start, uint64_t end); > +uint64_t get_current_el(void); > +void set_mair_tcr_ttbr_sctlr_el1(uint64_t page_table, uint64_t tcr_flags); > +void set_mair_tcr_ttbr_sctlr_el2(uint64_t page_table, uint64_t tcr_flags); > +void set_mair_tcr_ttbr_sctlr_el3(uint64_t page_table, uint64_t tcr_flags); > +void invalidate_tlbs_el1(void); > +void invalidate_tlbs_el2(void); > +void invalidate_tlbs_el3(void); > +void invalidate_icache(void); > +void reset_sctlr_el1(void); > +void reset_sctlr_el2(void); > +void reset_sctlr_el3(void); > +#else > +#define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_NGNRNE*8)) | \ > + (0x04 << (MT_DEVICE_NGNRE*8)) | \ > + (0x0C << (MT_DEVICE_GRE*8)) | \ > + (0x44 << (MT_NORMAL_NC*8)) | \ > + (0xFF << (MT_NORMAL*8))) > + > +/* Common SCTLR_ELx flags. */ > +#define SCTLR_ELx_I (1 << 12) > +#define SCTLR_ELx_C (1 << 2) > +#define SCTLR_ELx_M (1 << 0) > + > +#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_I) > + > +#endif > +#endif >