From eb68ea9b10c190c237216dee92166f9e7b2ce3d4 Mon Sep 17 00:00:00 2001
From: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Date: Fri, 22 Sep 2017 08:32:09 +0100
Subject: [PATCH] GIC: Add API to get running priority

Document the API in separate platform interrupt controller API document.

Change-Id: If18f208e10a8a243f5c59d226fcf48e985941949
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
---
 docs/platform-interrupt-controller-API.rst | 32 ++++++++++++++++++++++
 docs/porting-guide.rst                     |  6 +++-
 drivers/arm/gic/v2/gicv2_main.c            | 12 ++++++++
 drivers/arm/gic/v2/gicv2_private.h         |  7 ++++-
 drivers/arm/gic/v3/gicv3_main.c            |  9 ++++++
 include/drivers/arm/gicv2.h                |  3 +-
 include/drivers/arm/gicv3.h                |  2 ++
 include/lib/aarch32/arch_helpers.h         |  1 +
 include/lib/aarch64/arch.h                 |  1 +
 include/lib/aarch64/arch_helpers.h         |  1 +
 include/plat/common/platform.h             |  5 ++++
 plat/common/plat_gicv2.c                   |  9 +++++-
 plat/common/plat_gicv3.c                   | 10 ++++++-
 13 files changed, 93 insertions(+), 5 deletions(-)
 create mode 100644 docs/platform-interrupt-controller-API.rst

diff --git a/docs/platform-interrupt-controller-API.rst b/docs/platform-interrupt-controller-API.rst
new file mode 100644
index 000000000..9ef2e3f67
--- /dev/null
+++ b/docs/platform-interrupt-controller-API.rst
@@ -0,0 +1,32 @@
+Platform Interrupt Controller API documentation
+===============================================
+
+.. section-numbering::
+    :suffix: .
+
+.. contents::
+
+This document lists the optional platform interrupt controller API that
+abstracts the runtime configuration and control of interrupt controller from the
+generic code. The mandatory APIs are described in the `porting guide`__.
+
+.. __: porting-guide.rst#interrupt-management-framework-in-bl31
+
+Function: unsigned int plat_ic_get_running_priority(void); [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : unsigned int
+
+This API should return the priority of the interrupt the PE is currently
+servicing. This must be be called only after an interrupt has already been
+acknowledged via. ``plat_ic_acknowledge_interrupt``.
+
+In the case of ARM standard platforms using GIC, the *Running Priority Register*
+is read to determine the priority of the interrupt.
+
+----
+
+*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 6c07b2eb3..c0b173c6a 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2289,6 +2289,10 @@ Standard layer to use GICv2 and the FVP can be configured to use either GICv2 or
 GICv3 depending on the build flag ``FVP_USE_GIC_DRIVER`` (See FVP platform
 specific build options in `User Guide`_ for more details).
 
+See also: `Interrupt Controller Abstraction APIs`__.
+
+.. __: platform-interrupt-controller-API.rst
+
 Function : plat\_interrupt\_type\_to\_line() [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -2636,7 +2640,7 @@ amount of open resources per driver.
 
 --------------
 
-*Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.*
 
 .. _Migration Guide: platform-migration-guide.rst
 .. _include/plat/common/platform.h: ../include/plat/common/platform.h
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index deac927ca..7759a551a 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -240,3 +240,15 @@ unsigned int gicv2_get_interrupt_group(unsigned int id)
 
 	return gicd_get_igroupr(driver_data->gicd_base, id);
 }
+
+/*******************************************************************************
+ * This function returns the priority of the interrupt the processor is
+ * currently servicing.
+ ******************************************************************************/
+unsigned int gicv2_get_running_priority(void)
+{
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	return gicc_read_rpr(driver_data->gicc_base);
+}
diff --git a/drivers/arm/gic/v2/gicv2_private.h b/drivers/arm/gic/v2/gicv2_private.h
index 91ab43a2b..7703cbe55 100644
--- a/drivers/arm/gic/v2/gicv2_private.h
+++ b/drivers/arm/gic/v2/gicv2_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -80,6 +80,11 @@ static inline unsigned int gicc_read_iidr(uintptr_t base)
 	return mmio_read_32(base + GICC_IIDR);
 }
 
+static inline unsigned int gicc_read_rpr(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_RPR);
+}
+
 /*******************************************************************************
  * GIC CPU interface accessors for writing entire registers
  ******************************************************************************/
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 1a018d809..7e7574306 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -769,3 +769,12 @@ void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)
 	gicd_wait_for_pending_write(gicd_base);
 
 }
+
+/*******************************************************************************
+ * This function gets the priority of the interrupt the processor is currently
+ * servicing.
+ ******************************************************************************/
+unsigned int gicv3_get_running_priority(void)
+{
+	return read_icc_rpr_el1();
+}
diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h
index a78802545..1ef0779b9 100644
--- a/include/drivers/arm/gicv2.h
+++ b/include/drivers/arm/gicv2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -136,6 +136,7 @@ unsigned int gicv2_get_pending_interrupt_id(void);
 unsigned int gicv2_acknowledge_interrupt(void);
 void gicv2_end_of_interrupt(unsigned int id);
 unsigned int gicv2_get_interrupt_group(unsigned int id);
+unsigned int gicv2_get_running_priority(void);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV2_H__ */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index c52fe4833..4548a87c8 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -349,5 +349,7 @@ void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_
 void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx);
 void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx);
 
+unsigned int gicv3_get_running_priority(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV3_H__ */
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 5d3183603..1f4f21625 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -257,6 +257,7 @@ DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE)
 DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE)
 DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE)
 DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR)
+DEFINE_COPROCR_RW_FUNCS(icc_rpr_el1, ICC_RPR)
 DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1)
 DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0)
 DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0)
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index f85e78971..3fb6846c8 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -68,6 +68,7 @@
 #define ICC_CTLR_EL1    S3_0_C12_C12_4
 #define ICC_CTLR_EL3    S3_6_C12_C12_4
 #define ICC_PMR_EL1     S3_0_C4_C6_0
+#define ICC_RPR_EL1     S3_0_C12_C11_3
 #define ICC_IGRPEN1_EL3 S3_6_c12_c12_7
 #define ICC_IGRPEN0_EL1 S3_0_c12_c12_6
 #define ICC_HPPIR0_EL1  S3_0_c12_c8_2
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 0d0d7d335..dbbbaeb0b 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -313,6 +313,7 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1)
 DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1)
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index e189f648a..7468352d1 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -69,6 +69,11 @@ void plat_ic_end_of_interrupt(uint32_t id);
 uint32_t plat_interrupt_type_to_line(uint32_t type,
 				     uint32_t security_state);
 
+/*******************************************************************************
+ * Optional interrupt management functions, depending on chosen EL3 components.
+ ******************************************************************************/
+unsigned int plat_ic_get_running_priority(void);
+
 /*******************************************************************************
  * Optional common functions (may be overridden)
  ******************************************************************************/
diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c
index 50a81818c..1be693bb3 100644
--- a/plat/common/plat_gicv2.c
+++ b/plat/common/plat_gicv2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,8 @@
 #pragma weak plat_ic_end_of_interrupt
 #pragma weak plat_interrupt_type_to_line
 
+#pragma weak plat_ic_get_running_priority
+
 /*
  * This function returns the highest priority pending interrupt at
  * the Interrupt controller
@@ -122,3 +124,8 @@ uint32_t plat_interrupt_type_to_line(uint32_t type,
 	return ((gicv2_is_fiq_enabled()) ? __builtin_ctz(SCR_FIQ_BIT) :
 						__builtin_ctz(SCR_IRQ_BIT));
 }
+
+unsigned int plat_ic_get_running_priority(void)
+{
+	return gicv2_get_running_priority();
+}
diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c
index 030a1d902..02317f1df 100644
--- a/plat/common/plat_gicv3.c
+++ b/plat/common/plat_gicv3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,6 +26,8 @@
 #pragma weak plat_ic_end_of_interrupt
 #pragma weak plat_interrupt_type_to_line
 
+#pragma weak plat_ic_get_running_priority
+
 CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
 	(INTR_TYPE_NS == INTR_GROUP1NS) &&
 	(INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch);
@@ -155,6 +157,12 @@ uint32_t plat_interrupt_type_to_line(uint32_t type,
 		return __builtin_ctz(SCR_FIQ_BIT);
 	}
 }
+
+unsigned int plat_ic_get_running_priority(void)
+{
+	return gicv3_get_running_priority();
+}
+
 #endif
 #ifdef IMAGE_BL32
 
-- 
GitLab