xlat v2: Introduce xlat granule size helpers

The function xlat_arch_is_granule_size_supported() can be used to check
if a specific granule size is supported. In Armv8, AArch32 only supports
4 KiB pages. AArch64 supports 4 KiB, 16 KiB or 64 KiB depending on the
implementation, which is detected at runtime.

The function xlat_arch_get_max_supported_granule_size() returns the max
granule size supported by the implementation.

Even though right now they are only used by SPM, they may be useful in
other places in the future. This patch moves the code currently in SPM
to the xlat tables lib so that it can be reused.

Change-Id: If54624a5ecf20b9b9b7f38861b56383a03bbc8a4
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/include/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h
index d83d764..7795317 100644
--- a/include/lib/xlat_tables/xlat_mmu_helpers.h
+++ b/include/lib/xlat_tables/xlat_mmu_helpers.h
@@ -43,6 +43,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <sys/types.h>
+
 #ifdef AARCH32
 /* AArch32 specific translation table API */
 void enable_mmu_secure(unsigned int flags);
@@ -52,6 +54,9 @@
 void enable_mmu_el3(unsigned int flags);
 #endif /* AARCH32 */
 
+int xlat_arch_is_granule_size_supported(size_t size);
+size_t xlat_arch_get_max_supported_granule_size(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __XLAT_MMU_HELPERS_H__ */
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 7d67a4a..f66f802 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -18,6 +18,23 @@
 #error ARMv7 target does not support LPAE MMU descriptors
 #endif
 
+/*
+ * Returns 1 if the provided granule size is supported, 0 otherwise.
+ */
+int xlat_arch_is_granule_size_supported(size_t size)
+{
+	/*
+	 * The Trusted Firmware uses long descriptor translation table format,
+	 * which supports 4 KiB pages only.
+	 */
+	return (size == (4U * 1024U));
+}
+
+size_t xlat_arch_get_max_supported_granule_size(void)
+{
+	return 4U * 1024U;
+}
+
 #if ENABLE_ASSERTIONS
 unsigned long long xlat_arch_get_max_supported_pa(void)
 {
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index b3504e1..c501e70 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -16,6 +16,42 @@
 #include <xlat_tables_v2.h>
 #include "../xlat_tables_private.h"
 
+/*
+ * Returns 1 if the provided granule size is supported, 0 otherwise.
+ */
+int xlat_arch_is_granule_size_supported(size_t size)
+{
+	u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
+
+	if (size == (4U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
+	} else if (size == (16U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
+	} else if (size == (64U * 1024U)) {
+		return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
+			 ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
+			 ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
+	}
+
+	return 0;
+}
+
+size_t xlat_arch_get_max_supported_granule_size(void)
+{
+	if (xlat_arch_is_granule_size_supported(64U * 1024U)) {
+		return 64U * 1024U;
+	} else if (xlat_arch_is_granule_size_supported(16U * 1024U)) {
+		return 16U * 1024U;
+	} else {
+		assert(xlat_arch_is_granule_size_supported(4U * 1024U));
+		return 4U * 1024U;
+	}
+}
+
 unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr)
 {
 	/* Physical address can't exceed 48 bits */
diff --git a/services/std_svc/spm/sp_setup.c b/services/std_svc/spm/sp_setup.c
index 13dede7..b9b67f7 100644
--- a/services/std_svc/spm/sp_setup.c
+++ b/services/std_svc/spm/sp_setup.c
@@ -75,45 +75,18 @@
 #if ENABLE_ASSERTIONS
 
 	/* Get max granularity supported by the platform. */
+	unsigned int max_granule = xlat_arch_get_max_supported_granule_size();
 
-	u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
+	VERBOSE("Max translation granule size supported: %u KiB\n",
+		max_granule / 1024U);
 
-	int tgran64_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN64_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED;
-
-	int tgran16_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN16_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED;
-
-	int tgran4_supported =
-		((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) &
-		 ID_AA64MMFR0_EL1_TGRAN4_MASK) ==
-		 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED;
-
-	uintptr_t max_granule_size;
-
-	if (tgran64_supported) {
-		max_granule_size = 64 * 1024;
-	} else if (tgran16_supported) {
-		max_granule_size = 16 * 1024;
-	} else {
-		assert(tgran4_supported);
-		max_granule_size = 4 * 1024;
-	}
-
-	VERBOSE("Max translation granule supported: %lu KiB\n",
-		max_granule_size / 1024);
-
-	uintptr_t max_granule_size_mask = max_granule_size - 1;
+	unsigned int max_granule_mask = max_granule - 1U;
 
 	/* Base must be aligned to the max granularity */
-	assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_size_mask) == 0);
+	assert((ARM_SP_IMAGE_NS_BUF_BASE & max_granule_mask) == 0);
 
 	/* Size must be a multiple of the max granularity */
-	assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_size_mask) == 0);
+	assert((ARM_SP_IMAGE_NS_BUF_SIZE & max_granule_mask) == 0);
 
 #endif /* ENABLE_ASSERTIONS */