xlat lib: Introduce MT_EXECUTE/MT_EXECUTE_NEVER attributes

This patch introduces the MT_EXECUTE/MT_EXECUTE_NEVER memory mapping
attributes in the translation table library to specify the
access permissions for instruction execution of a memory region.
These new attributes should be used only for normal, read-only
memory regions. For other types of memory, the translation table
library still enforces the following rules, regardless of the
MT_EXECUTE/MT_EXECUTE_NEVER attribute:

 - Device memory is always marked as execute-never.
 - Read-write normal memory is always marked as execute-never.

Change-Id: I8bd27800a8c1d8ac1559910caf4a4840cf25b8b0
diff --git a/include/lib/xlat_tables.h b/include/lib/xlat_tables.h
index 7d57521..b51a1de 100644
--- a/include/lib/xlat_tables.h
+++ b/include/lib/xlat_tables.h
@@ -134,6 +134,8 @@
 #define MT_PERM_SHIFT	3
 /* Security state (SECURE/NS) */
 #define MT_SEC_SHIFT	4
+/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
+#define MT_EXECUTE_SHIFT	5
 
 /*
  * Memory mapping attributes
@@ -155,8 +157,21 @@
 
 	MT_SECURE	= 0 << MT_SEC_SHIFT,
 	MT_NS		= 1 << MT_SEC_SHIFT,
+
+	/*
+	 * Access permissions for instruction execution are only relevant for
+	 * normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
+	 * (and potentially overridden) otherwise:
+	 *  - Device memory is always marked as execute-never.
+	 *  - Read-write normal memory is always marked as execute-never.
+	 */
+	MT_EXECUTE		= 0 << MT_EXECUTE_SHIFT,
+	MT_EXECUTE_NEVER	= 1 << MT_EXECUTE_SHIFT,
 } mmap_attr_t;
 
+#define MT_CODE		(MT_MEMORY | MT_RO | MT_EXECUTE)
+#define MT_RO_DATA	(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+
 /*
  * Structure for specifying a single region of memory.
  */
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index a840189..e1448b9 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -234,8 +234,11 @@
 		 * 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)
+		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER))
 			desc |= UPPER_ATTRS(XN);
 
 		if (mem_type == MT_MEMORY) {
@@ -250,7 +253,7 @@
 		((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;
 }