Optimize cache flush when authenticating images

When loading and authenticating an image, all parent images must also
be authenticated. The parent images are just certificates that don't
need to be used by any other CPU except the one loading the image, and
so there is no need to flush the cache of memory regions where they
are loaded.

Change-Id: Ice8d6979d1c02eabf1a543281ae1a07d098e4a99
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
diff --git a/common/bl_common.c b/common/bl_common.c
index 193e972..15d5bde 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -315,14 +315,9 @@
 	return io_result;
 }
 
-/*******************************************************************************
- * Generic function to load and authenticate an image. The image is actually
- * loaded by calling the 'load_image()' function. Therefore, it returns the
- * same error codes if the loading operation failed, or -EAUTH if the
- * authentication failed. In addition, this function uses recursion to
- * authenticate the parent images up to the root of trust.
- ******************************************************************************/
-int load_auth_image(unsigned int image_id, image_info_t *image_data)
+static int load_auth_image_internal(unsigned int image_id,
+				    image_info_t *image_data,
+				    int is_parent_image)
 {
 	int rc;
 
@@ -332,7 +327,7 @@
 	/* Use recursion to authenticate parent images */
 	rc = auth_mod_get_parent_id(image_id, &parent_id);
 	if (rc == 0) {
-		rc = load_auth_image(parent_id, image_data);
+		rc = load_auth_image_internal(parent_id, image_data, 1);
 		if (rc != 0) {
 			return rc;
 		}
@@ -351,6 +346,7 @@
 				 (void *)image_data->image_base,
 				 image_data->image_size);
 	if (rc != 0) {
+		/* Authentication error, zero memory and flush it right away. */
 		memset((void *)image_data->image_base, 0x00,
 		       image_data->image_size);
 		flush_dcache_range(image_data->image_base,
@@ -362,13 +358,29 @@
 	 * File has been successfully loaded and authenticated.
 	 * Flush the image to main memory so that it can be executed later by
 	 * any CPU, regardless of cache and MMU state.
+	 * Do it only for child images, not for the parents (certificates).
 	 */
-	flush_dcache_range(image_data->image_base, image_data->image_size);
+	if (!is_parent_image) {
+		flush_dcache_range(image_data->image_base,
+				   image_data->image_size);
+	}
 #endif /* TRUSTED_BOARD_BOOT */
 
 	return 0;
 }
 
+/*******************************************************************************
+ * Generic function to load and authenticate an image. The image is actually
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
+ ******************************************************************************/
+int load_auth_image(unsigned int image_id, image_info_t *image_data)
+{
+	return load_auth_image_internal(image_id, image_data, 0);
+}
+
 #else /* LOAD_IMAGE_V2 */
 
 /*******************************************************************************
@@ -494,18 +506,12 @@
 	return io_result;
 }
 
-/*******************************************************************************
- * Generic function to load and authenticate an image. The image is actually
- * loaded by calling the 'load_image()' function. Therefore, it returns the
- * same error codes if the loading operation failed, or -EAUTH if the
- * authentication failed. In addition, this function uses recursion to
- * authenticate the parent images up to the root of trust.
- ******************************************************************************/
-int load_auth_image(meminfo_t *mem_layout,
-		    unsigned int image_id,
-		    uintptr_t image_base,
-		    image_info_t *image_data,
-		    entry_point_info_t *entry_point_info)
+static int load_auth_image_internal(meminfo_t *mem_layout,
+				    unsigned int image_id,
+				    uintptr_t image_base,
+				    image_info_t *image_data,
+				    entry_point_info_t *entry_point_info,
+				    int is_parent_image)
 {
 	int rc;
 
@@ -515,8 +521,8 @@
 	/* Use recursion to authenticate parent images */
 	rc = auth_mod_get_parent_id(image_id, &parent_id);
 	if (rc == 0) {
-		rc = load_auth_image(mem_layout, parent_id, image_base,
-				     image_data, NULL);
+		rc = load_auth_image_internal(mem_layout, parent_id, image_base,
+				     image_data, NULL, 1);
 		if (rc != 0) {
 			return rc;
 		}
@@ -536,6 +542,7 @@
 				 (void *)image_data->image_base,
 				 image_data->image_size);
 	if (rc != 0) {
+		/* Authentication error, zero memory and flush it right away. */
 		memset((void *)image_data->image_base, 0x00,
 		       image_data->image_size);
 		flush_dcache_range(image_data->image_base,
@@ -546,13 +553,34 @@
 	 * File has been successfully loaded and authenticated.
 	 * Flush the image to main memory so that it can be executed later by
 	 * any CPU, regardless of cache and MMU state.
+	 * Do it only for child images, not for the parents (certificates).
 	 */
-	flush_dcache_range(image_data->image_base, image_data->image_size);
+	if (!is_parent_image) {
+		flush_dcache_range(image_data->image_base,
+				   image_data->image_size);
+	}
 #endif /* TRUSTED_BOARD_BOOT */
 
 	return 0;
 }
 
+/*******************************************************************************
+ * Generic function to load and authenticate an image. The image is actually
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
+ ******************************************************************************/
+int load_auth_image(meminfo_t *mem_layout,
+		    unsigned int image_id,
+		    uintptr_t image_base,
+		    image_info_t *image_data,
+		    entry_point_info_t *entry_point_info)
+{
+	return load_auth_image_internal(mem_layout, image_id, image_base,
+					image_data, entry_point_info, 0);
+}
+
 #endif /* LOAD_IMAGE_V2 */
 
 /*******************************************************************************