diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/xlat_tables/aarch32/xlat_tables.c | 14 | ||||
| -rw-r--r-- | lib/xlat_tables/aarch64/xlat_tables.c | 19 | ||||
| -rw-r--r-- | lib/xlat_tables/xlat_tables_common.c | 14 | ||||
| -rw-r--r-- | lib/xlat_tables/xlat_tables_private.h | 11 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/aarch32/xlat_tables_arch.c | 14 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/aarch64/xlat_tables_arch.c | 19 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/xlat_tables_common.c | 2 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/xlat_tables_internal.c | 28 | ||||
| -rw-r--r-- | lib/xlat_tables_v2/xlat_tables_private.h | 17 | 
9 files changed, 121 insertions, 17 deletions
| diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c index 4fe5bf91..6033522a 100644 --- a/lib/xlat_tables/aarch32/xlat_tables.c +++ b/lib/xlat_tables/aarch32/xlat_tables.c @@ -93,6 +93,20 @@ static unsigned long long get_max_supported_pa(void)  }  #endif /* ENABLE_ASSERTIONS */ +int xlat_arch_current_el(void) +{ +	/* +	 * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System, +	 * SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. +	 */ +	return 3; +} + +uint64_t xlat_arch_get_xn_desc(int el __unused) +{ +	return UPPER_ATTRS(XN); +} +  void init_xlat_tables(void)  {  	unsigned long long max_pa; diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c index 4f237936..7be36ca3 100644 --- a/lib/xlat_tables/aarch64/xlat_tables.c +++ b/lib/xlat_tables/aarch64/xlat_tables.c @@ -146,6 +146,25 @@ static unsigned long long get_max_supported_pa(void)  }  #endif /* ENABLE_ASSERTIONS */ +int xlat_arch_current_el(void) +{ +	int el = GET_EL(read_CurrentEl()); + +	assert(el > 0); + +	return el; +} + +uint64_t xlat_arch_get_xn_desc(int el) +{ +	if (el == 3) { +		return UPPER_ATTRS(XN); +	} else { +		assert(el == 1); +		return UPPER_ATTRS(PXN); +	} +} +  void init_xlat_tables(void)  {  	unsigned long long max_pa; diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index 23f3daa8..1f21470c 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -64,6 +64,8 @@ static unsigned next_xlat;  static unsigned long long xlat_max_pa;  static uintptr_t xlat_max_va; +static uint64_t execute_never_mask; +  /*   * Array of all memory regions stored in order of ascending base address.   * The list is terminated by the first entry with size == 0. @@ -237,7 +239,8 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * fetch, which could be an issue if this memory region  		 * corresponds to a read-sensitive peripheral.  		 */ -		desc |= UPPER_ATTRS(XN); +		desc |= execute_never_mask; +  	} else { /* Normal memory */  		/*  		 * Always map read-write normal memory as execute-never. @@ -245,7 +248,7 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * R/W memory is reserved for data storage, which must not be  		 * executable.)  		 * Note that setting the XN bit here is for consistency only. -		 * The enable_mmu_elx() function sets the SCTLR_EL3.WXN bit, +		 * The function that enables the MMU sets the SCTLR_ELx.WXN bit,  		 * which makes any writable memory region to be treated as  		 * execute-never, regardless of the value of the XN bit in the  		 * translation table. @@ -253,8 +256,9 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER  		 * attribute to figure out the value of the XN bit.  		 */ -		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) -			desc |= UPPER_ATTRS(XN); +		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) { +			desc |= execute_never_mask; +		}  		if (mem_type == MT_MEMORY) {  			desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); @@ -401,7 +405,7 @@ void init_xlation_table(uintptr_t base_va, uint64_t *table,  			int level, uintptr_t *max_va,  			unsigned long long *max_pa)  { - +	execute_never_mask = xlat_arch_get_xn_desc(xlat_arch_current_el());  	init_xlation_table_inner(mmap, base_va, table, level);  	*max_va = xlat_max_va;  	*max_pa = xlat_max_pa; diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h index 54ad909f..ea633373 100644 --- a/lib/xlat_tables/xlat_tables_private.h +++ b/lib/xlat_tables/xlat_tables_private.h @@ -89,6 +89,17 @@ CASSERT(IS_POWER_OF_TWO(PLAT_PHY_ADDR_SPACE_SIZE),  #endif /* AARCH32 */  void print_mmap(void); + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +int xlat_arch_current_el(void); + +/* + * Returns the bit mask that has to be ORed to the rest of a translation table + * descriptor so that execution of code is prohibited at the given Exception + * Level. + */ +uint64_t xlat_arch_get_xn_desc(int el); +  void init_xlation_table(uintptr_t base_va, uint64_t *table,  			int level, uintptr_t *max_va,  			unsigned long long *max_pa); diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c index cd7aad8f..cb1f92db 100644 --- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -91,6 +91,20 @@ void xlat_arch_tlbi_va_sync(void)  #endif /* PLAT_XLAT_TABLES_DYNAMIC */ +int xlat_arch_current_el(void) +{ +	/* +	 * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System, +	 * SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. +	 */ +	return 3; +} + +uint64_t xlat_arch_get_xn_desc(int el __unused) +{ +	return UPPER_ATTRS(XN); +} +  void init_xlat_tables_arch(unsigned long long max_pa)  {  	assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <= diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c index 24266b2d..31e39cf4 100644 --- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -151,6 +151,25 @@ void xlat_arch_tlbi_va_sync(void)  #endif /* PLAT_XLAT_TABLES_DYNAMIC */ +int xlat_arch_current_el(void) +{ +	int el = GET_EL(read_CurrentEl()); + +	assert(el > 0); + +	return el; +} + +uint64_t xlat_arch_get_xn_desc(int el) +{ +	if (el == 3) { +		return UPPER_ATTRS(XN); +	} else { +		assert(el == 1); +		return UPPER_ATTRS(PXN); +	} +} +  void init_xlat_tables_arch(unsigned long long max_pa)  {  	assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <= diff --git a/lib/xlat_tables_v2/xlat_tables_common.c b/lib/xlat_tables_v2/xlat_tables_common.c index 7ca81b9c..9f84b22e 100644 --- a/lib/xlat_tables_v2/xlat_tables_common.c +++ b/lib/xlat_tables_v2/xlat_tables_common.c @@ -137,6 +137,8 @@ void init_xlat_tables(void)  	assert(!is_mmu_enabled());  	assert(!tf_xlat_ctx.initialized);  	print_mmap(tf_xlat_ctx.mmap); +	tf_xlat_ctx.execute_never_mask = +			xlat_arch_get_xn_desc(xlat_arch_current_el());  	init_xlation_table(&tf_xlat_ctx);  	xlat_tables_print(&tf_xlat_ctx); diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c index 581f7703..e7c67a46 100644 --- a/lib/xlat_tables_v2/xlat_tables_internal.c +++ b/lib/xlat_tables_v2/xlat_tables_internal.c @@ -116,7 +116,7 @@ static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx)  /* Returns a block/page table descriptor for the given level and attributes. */  static uint64_t xlat_desc(mmap_attr_t attr, unsigned long long addr_pa, -			  int level) +			  int level, uint64_t execute_never_mask)  {  	uint64_t desc;  	int mem_type; @@ -158,7 +158,8 @@ static uint64_t xlat_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * fetch, which could be an issue if this memory region  		 * corresponds to a read-sensitive peripheral.  		 */ -		desc |= UPPER_ATTRS(XN); +		desc |= execute_never_mask; +  	} else { /* Normal memory */  		/*  		 * Always map read-write normal memory as execute-never. @@ -166,7 +167,7 @@ static uint64_t xlat_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * R/W memory is reserved for data storage, which must not be  		 * executable.)  		 * Note that setting the XN bit here is for consistency only. -		 * The enable_mmu_elx() function sets the SCTLR_EL3.WXN bit, +		 * The function that enables the MMU sets the SCTLR_ELx.WXN bit,  		 * which makes any writable memory region to be treated as  		 * execute-never, regardless of the value of the XN bit in the  		 * translation table. @@ -174,8 +175,9 @@ static uint64_t xlat_desc(mmap_attr_t attr, unsigned long long addr_pa,  		 * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER  		 * attribute to figure out the value of the XN bit.  		 */ -		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) -			desc |= UPPER_ATTRS(XN); +		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) { +			desc |= execute_never_mask; +		}  		if (mem_type == MT_MEMORY) {  			desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); @@ -535,7 +537,8 @@ static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,  		if (action == ACTION_WRITE_BLOCK_ENTRY) {  			table_base[table_idx] = -				xlat_desc(mm->attr, table_idx_pa, level); +				xlat_desc(mm->attr, table_idx_pa, level, +					  ctx->execute_never_mask);  		} else if (action == ACTION_CREATE_NEW_TABLE) { @@ -940,7 +943,7 @@ int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va,  #if LOG_LEVEL >= LOG_LEVEL_VERBOSE  /* Print the attributes of the specified block descriptor. */ -static void xlat_desc_print(uint64_t desc) +static void xlat_desc_print(uint64_t desc, uint64_t execute_never_mask)  {  	int mem_type_index = ATTR_INDEX_GET(desc); @@ -955,7 +958,7 @@ static void xlat_desc_print(uint64_t desc)  	tf_printf(LOWER_ATTRS(AP_RO) & desc ? "-RO" : "-RW");  	tf_printf(LOWER_ATTRS(NS) & desc ? "-NS" : "-S"); -	tf_printf(UPPER_ATTRS(XN) & desc ? "-XN" : "-EXEC"); +	tf_printf(execute_never_mask & desc ? "-XN" : "-EXEC");  }  static const char * const level_spacers[] = { @@ -974,7 +977,7 @@ static const char *invalid_descriptors_ommited =   */  static void xlat_tables_print_internal(const uintptr_t table_base_va,  		uint64_t *const table_base, const int table_entries, -		const int level) +		const int level, const uint64_t execute_never_mask)  {  	assert(level <= XLAT_TABLE_LEVEL_MAX); @@ -1035,14 +1038,15 @@ static void xlat_tables_print_internal(const uintptr_t table_base_va,  				xlat_tables_print_internal(table_idx_va,  					(uint64_t *)addr_inner, -					XLAT_TABLE_ENTRIES, level+1); +					XLAT_TABLE_ENTRIES, level+1, +					execute_never_mask);  			} else {  				tf_printf("%sVA:%p PA:0x%llx size:0x%zx ",  					  level_spacers[level],  					  (void *)table_idx_va,  					  (unsigned long long)(desc & TABLE_ADDR_MASK),  					  level_size); -				xlat_desc_print(desc); +				xlat_desc_print(desc, execute_never_mask);  				tf_printf("\n");  			}  		} @@ -1063,7 +1067,7 @@ void xlat_tables_print(xlat_ctx_t *ctx)  {  #if LOG_LEVEL >= LOG_LEVEL_VERBOSE  	xlat_tables_print_internal(0, ctx->base_table, ctx->base_table_entries, -				   ctx->base_level); +				   ctx->base_level, ctx->execute_never_mask);  #endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */  } diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h index e79890e5..465f2a4f 100644 --- a/lib/xlat_tables_v2/xlat_tables_private.h +++ b/lib/xlat_tables_v2/xlat_tables_private.h @@ -108,6 +108,13 @@ typedef struct {  	/* Set to 1 when the translation tables are initialized. */  	int initialized; +	/* +	 * Bit mask that has to be ORed to the rest of a translation table +	 * descriptor in order to prohibit execution of code at the exception +	 * level of this translation context. +	 */ +	uint64_t execute_never_mask; +  } xlat_ctx_t;  #if PLAT_XLAT_TABLES_DYNAMIC @@ -178,6 +185,16 @@ void mmap_add_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm);   * Architecture-specific initialization code.   */ +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +int xlat_arch_current_el(void); + +/* + * Returns the bit mask that has to be ORed to the rest of a translation table + * descriptor so that execution of code is prohibited at the given Exception + * Level. + */ +uint64_t xlat_arch_get_xn_desc(int el); +  /* Execute architecture-specific translation table initialization code. */  void init_xlat_tables_arch(unsigned long long max_pa); | 
