qemu: Support SEPARATE_CODE_AND_RODATA

Update qemu_configure_mmu_##_el to add an additional region for code,
marked as MT_CODE | MT_SECURE. Update ro region attributes to NON_EXEC.

Update calls to QEMU_CONFIGURE_BLx_MMU() to pass an additional region for
code. Update calls to pass regions defined in common_def.h.

Increase MAX_MMAP_REGIONS to 10.

Enable SEPARATE_CODE_AND_RODATA by default on QEMU builds.

Fixes ARM-software/tf-issues#558

Signed-off-by: Michalis Pappas <mpappas@fastmail.fm>
diff --git a/plat/qemu/include/platform_def.h b/plat/qemu/include/platform_def.h
index afda4f8..98ed3bc 100644
--- a/plat/qemu/include/platform_def.h
+++ b/plat/qemu/include/platform_def.h
@@ -168,7 +168,7 @@
 
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
-#define MAX_MMAP_REGIONS		8
+#define MAX_MMAP_REGIONS		10
 #define MAX_XLAT_TABLES			6
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk
index 26633c2..5bfd48a 100644
--- a/plat/qemu/platform.mk
+++ b/plat/qemu/platform.mk
@@ -167,6 +167,8 @@
 $(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
 endif
 
+SEPARATE_CODE_AND_RODATA := 1
+
 # Disable the PSCI platform compatibility layer
 ENABLE_PLAT_COMPAT	:= 	0
 
diff --git a/plat/qemu/qemu_bl1_setup.c b/plat/qemu/qemu_bl1_setup.c
index 7c820fd..3f617e2 100644
--- a/plat/qemu/qemu_bl1_setup.c
+++ b/plat/qemu/qemu_bl1_setup.c
@@ -12,15 +12,6 @@
 #include <platform_def.h>
 #include "qemu_private.h"
 
-/*******************************************************************************
- * Declarations of linker defined symbols which will tell us where BL1 lives
- * in Trusted RAM
- ******************************************************************************/
-extern uint64_t __BL1_RAM_START__;
-extern uint64_t __BL1_RAM_END__;
-#define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__)
-#define BL1_RAM_LIMIT (uint64_t)(&__BL1_RAM_END__)
-
 /* Data structure which holds the extents of the trusted SRAM for BL1*/
 static meminfo_t bl1_tzram_layout;
 
@@ -67,7 +58,8 @@
 {
 	QEMU_CONFIGURE_BL1_MMU(bl1_tzram_layout.total_base,
 				bl1_tzram_layout.total_size,
-				BL1_RO_BASE, BL1_RO_LIMIT,
+				BL_CODE_BASE, BL1_CODE_END,
+				BL1_RO_DATA_BASE, BL1_RO_DATA_END,
 				BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
 }
 
diff --git a/plat/qemu/qemu_bl2_setup.c b/plat/qemu/qemu_bl2_setup.c
index 9e4a4a0..987c602 100644
--- a/plat/qemu/qemu_bl2_setup.c
+++ b/plat/qemu/qemu_bl2_setup.c
@@ -17,14 +17,6 @@
 #include <utils.h>
 #include "qemu_private.h"
 
-/*
- * The next 2 constants identify the extents of the code & RO data region.
- * These addresses are used by the MMU setup code and therefore they must be
- * page-aligned.  It is the responsibility of the linker script to ensure that
- * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
- */
-#define BL2_RO_BASE (unsigned long)(&__RO_START__)
-#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
 
 /* Data structure which holds the extents of the trusted SRAM for BL2 */
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
@@ -192,7 +184,8 @@
 {
 	QEMU_CONFIGURE_BL2_MMU(bl2_tzram_layout.total_base,
 			      bl2_tzram_layout.total_size,
-			      BL2_RO_BASE, BL2_RO_LIMIT,
+			      BL_CODE_BASE, BL_CODE_END,
+			      BL_RO_DATA_BASE, BL_RO_DATA_END,
 			      BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
 }
 
diff --git a/plat/qemu/qemu_bl31_setup.c b/plat/qemu/qemu_bl31_setup.c
index f79a885..6ded929 100644
--- a/plat/qemu/qemu_bl31_setup.c
+++ b/plat/qemu/qemu_bl31_setup.c
@@ -19,8 +19,6 @@
  * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols
  * refer to page-aligned addresses.
  */
-#define BL31_RO_BASE (unsigned long)(&__RO_START__)
-#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
 #define BL31_END (unsigned long)(&__BL31_END__)
 
 /*
@@ -108,8 +106,9 @@
 
 void bl31_plat_arch_setup(void)
 {
-	qemu_configure_mmu_el3(BL31_RO_BASE, (BL31_END - BL31_RO_BASE),
-			      BL31_RO_BASE, BL31_RO_LIMIT,
+	qemu_configure_mmu_el3(BL31_BASE, (BL31_END - BL31_BASE),
+			      BL_CODE_BASE, BL_CODE_END,
+			      BL_RO_DATA_BASE, BL_RO_DATA_END,
 			      BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
 }
 
diff --git a/plat/qemu/qemu_common.c b/plat/qemu/qemu_common.c
index 6f9fcc6..2d4198b 100644
--- a/plat/qemu/qemu_common.c
+++ b/plat/qemu/qemu_common.c
@@ -104,6 +104,8 @@
 #define DEFINE_CONFIGURE_MMU_EL(_el)					\
 	void qemu_configure_mmu_##_el(unsigned long total_base,	\
 				   unsigned long total_size,		\
+				   unsigned long code_start,		\
+				   unsigned long code_limit,		\
 				   unsigned long ro_start,		\
 				   unsigned long ro_limit,		\
 				   unsigned long coh_start,		\
@@ -112,9 +114,12 @@
 		mmap_add_region(total_base, total_base,			\
 				total_size,				\
 				MT_MEMORY | MT_RW | MT_SECURE);		\
+		mmap_add_region(code_start, code_start,			\
+				code_limit - code_start,		\
+				MT_CODE | MT_SECURE);			\
 		mmap_add_region(ro_start, ro_start,			\
 				ro_limit - ro_start,			\
-				MT_MEMORY | MT_RO | MT_SECURE);		\
+				MT_RO_DATA | MT_SECURE);		\
 		mmap_add_region(coh_start, coh_start,			\
 				coh_limit - coh_start,			\
 				MT_DEVICE | MT_RW | MT_SECURE);		\
diff --git a/plat/qemu/qemu_private.h b/plat/qemu/qemu_private.h
index 202d604..716440f 100644
--- a/plat/qemu/qemu_private.h
+++ b/plat/qemu/qemu_private.h
@@ -9,16 +9,22 @@
 
 #include <sys/types.h>
 
+#include <xlat_tables_defs.h>
+#include "../../bl1/bl1_private.h"
+
 void qemu_configure_mmu_secure(unsigned long total_base,
 			unsigned long total_size,
+			unsigned long code_start, unsigned long code_limit,
 			unsigned long ro_start, unsigned long ro_limit,
 			unsigned long coh_start, unsigned long coh_limit);
 
 void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size,
+			unsigned long code_start, unsigned long code_limit,
 			unsigned long ro_start, unsigned long ro_limit,
 			unsigned long coh_start, unsigned long coh_limit);
 
 void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size,
+			unsigned long code_start, unsigned long code_limit,
 			unsigned long ro_start, unsigned long ro_limit,
 			unsigned long coh_start, unsigned long coh_limit);