summaryrefslogtreecommitdiff
path: root/lib/xlat_tables
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2017-05-05 09:50:34 +0100
committerGitHub <noreply@github.com>2017-05-05 09:50:34 +0100
commit5e6232778649fb1e6c6e0aa4671efe7e559ca78d (patch)
treeb687acdecbb4b7babab57d0f81452d6b83d7603e /lib/xlat_tables
parentf132b4a05b23916c1101add4bd6d973a99983719 (diff)
parenta56402521f80cf1b17e3936abcc6b1772aa91e66 (diff)
Merge pull request #924 from antonio-nino-diaz-arm/an/fix-xn-bit
Fix execute-never permissions in xlat tables libs
Diffstat (limited to 'lib/xlat_tables')
-rw-r--r--lib/xlat_tables/aarch32/xlat_tables.c14
-rw-r--r--lib/xlat_tables/aarch64/xlat_tables.c19
-rw-r--r--lib/xlat_tables/xlat_tables_common.c14
-rw-r--r--lib/xlat_tables/xlat_tables_private.h11
4 files changed, 53 insertions, 5 deletions
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index 03caf36f..3c9051c3 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -69,6 +69,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 2126180e..309cb9bd 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -122,6 +122,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 f322a9af..17e7e6e0 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -40,6 +40,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.
@@ -213,7 +215,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.
@@ -221,7 +224,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.
@@ -229,8 +232,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);
@@ -377,7 +381,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 d568dc0d..92078525 100644
--- a/lib/xlat_tables/xlat_tables_private.h
+++ b/lib/xlat_tables/xlat_tables_private.h
@@ -65,6 +65,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);