summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2016-07-15 18:55:43 +0100
committerGitHub <noreply@github.com>2016-07-15 18:55:43 +0100
commitaadb1350eed3c18aec6cd999519cef55d93678b3 (patch)
treed851cbd6afa9f9b14676cde93bbf4e49f0cfebf1 /lib
parent9306f135922bc7811dfc1e24a755c38ce2e671cd (diff)
parent91fad6551ee3e5529f9b442cd4a084251cdebe1d (diff)
Merge pull request #662 from sandrine-bailleux-arm/sb/rodata-xn
Map read-only data as execute-never
Diffstat (limited to 'lib')
-rw-r--r--lib/xlat_tables/aarch64/xlat_tables.c3
-rw-r--r--lib/xlat_tables/xlat_tables_common.c67
2 files changed, 49 insertions, 21 deletions
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 051e46a2..19eb7d5d 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -33,11 +33,10 @@
#include <assert.h>
#include <cassert.h>
#include <platform_def.h>
+#include <utils.h>
#include <xlat_tables.h>
#include "../xlat_tables_private.h"
-#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
-
/*
* The virtual address space size must be a power of two (as set in TCR.T0SZ).
* As we start the initial lookup at level 1, it must also be between 2 GB and
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index fd100846..71e3efca 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -31,11 +31,11 @@
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
-#include <bl_common.h>
#include <cassert.h>
#include <debug.h>
#include <platform_def.h>
#include <string.h>
+#include <utils.h>
#include <xlat_tables.h>
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
@@ -194,37 +194,66 @@ void mmap_add(const mmap_region_t *mm)
static uint64_t mmap_desc(unsigned attr, unsigned long long addr_pa,
int level)
{
- uint64_t desc = addr_pa;
+ uint64_t desc;
int mem_type;
- desc |= level == 3 ? TABLE_DESC : BLOCK_DESC;
-
- desc |= attr & MT_NS ? LOWER_ATTRS(NS) : 0;
-
- desc |= attr & MT_RW ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
-
+ desc = addr_pa;
+ desc |= (level == 3) ? TABLE_DESC : BLOCK_DESC;
+ desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
+ desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
desc |= LOWER_ATTRS(ACCESS_FLAG);
+ /*
+ * Deduce shareability domain and executability of the memory region
+ * from the memory type.
+ *
+ * Data accesses to device memory and non-cacheable normal memory are
+ * coherent for all observers in the system, and correspondingly are
+ * always treated as being Outer Shareable. Therefore, for these 2 types
+ * of memory, it is not strictly needed to set the shareability field
+ * in the translation tables.
+ */
mem_type = MT_TYPE(attr);
- if (mem_type == MT_MEMORY) {
- desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
- if (attr & MT_RW)
- desc |= UPPER_ATTRS(XN);
- } else if (mem_type == MT_NON_CACHEABLE) {
- desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
- if (attr & MT_RW)
- desc |= UPPER_ATTRS(XN);
- } else {
- assert(mem_type == MT_DEVICE);
+ if (mem_type == MT_DEVICE) {
desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
+ /*
+ * Always map device memory as execute-never.
+ * This is to avoid the possibility of a speculative instruction
+ * fetch, which could be an issue if this memory region
+ * corresponds to a read-sensitive peripheral.
+ */
desc |= UPPER_ATTRS(XN);
+ } else { /* Normal memory */
+ /*
+ * Always map read-write normal memory as execute-never.
+ * (Trusted Firmware doesn't self-modify its code, therefore
+ * 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,
+ * which makes any writable memory region to be treated as
+ * execute-never, regardless of the value of the XN bit in the
+ * translation table.
+ *
+ * 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 (mem_type == MT_MEMORY) {
+ desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
+ } else {
+ assert(mem_type == MT_NON_CACHEABLE);
+ desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
+ }
}
debug_print((mem_type == MT_MEMORY) ? "MEM" :
((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV"));
debug_print(attr & MT_RW ? "-RW" : "-RO");
debug_print(attr & MT_NS ? "-NS" : "-S");
-
+ debug_print(attr & MT_EXECUTE_NEVER ? "-XN" : "-EXEC");
return desc;
}