GIC: Add API to set priority mask
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>
Fri, 22 Sep 2017 07:32:09 +0000 (08:32 +0100)
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>
Mon, 16 Oct 2017 15:50:02 +0000 (16:50 +0100)
API documentation updated.

Change-Id: I40feec1fe67a960d035061b54dd55610bc34ce1d
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
docs/platform-interrupt-controller-API.rst
drivers/arm/gic/v2/gicv2_main.c
drivers/arm/gic/v3/gicv3_main.c
include/drivers/arm/gicv2.h
include/drivers/arm/gicv3.h
include/lib/aarch32/arch_helpers.h
include/lib/aarch64/arch_helpers.h
include/plat/common/platform.h
plat/common/plat_gicv2.c
plat/common/plat_gicv3.c

index d5c1673399f38f08f8e6b0c27f4fbb89a6d597a3..795c085625ccf3dcdb303f4d011996d18b9900f5 100644 (file)
@@ -274,6 +274,24 @@ In case of ARM standard platforms using GIC, the implementation of the API
 writes to the GIC *Clear Pending Register* to clear the interrupt pending
 status, and inserts barrier to make memory updates visible afterwards.
 
+Function: unsigned int plat_ic_set_priority_mask(unsigned int id); [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int
+    Return   : int
+
+This API should set the priority mask (first parameter) in the interrupt
+controller such that only interrupts of higher priority than the supplied one
+may be signalled to the PE. The API should return the current priority value
+that it's overwriting.
+
+In case of ARM standard platforms using GIC, the implementation of the API
+inserts to order memory updates before updating mask, then writes to the GIC
+*Priority Mask Register*, and make sure memory updates are visible before
+potential trigger due to mask update.
+
 ----
 
 *Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
index eab4c3bfedcf426d788f131e20626ee27d7488ad..59b6632329c9f6007f6f889d39783f3761ed0b8c 100644 (file)
@@ -476,3 +476,27 @@ void gicv2_set_interrupt_pending(unsigned int id)
        dsbishst();
        gicd_set_ispendr(driver_data->gicd_base, id);
 }
+
+/*******************************************************************************
+ * This function sets the PMR register with the supplied value. Returns the
+ * original PMR.
+ ******************************************************************************/
+unsigned int gicv2_set_pmr(unsigned int mask)
+{
+       unsigned int old_mask;
+
+       assert(driver_data);
+       assert(driver_data->gicc_base);
+
+       old_mask = gicc_read_pmr(driver_data->gicc_base);
+
+       /*
+        * Order memory updates w.r.t. PMR write, and ensure they're visible
+        * before potential out of band interrupt trigger because of PMR update.
+        */
+       dmbishst();
+       gicc_write_pmr(driver_data->gicc_base, mask);
+       dsbishst();
+
+       return old_mask;
+}
index 43dd77f126bb28f8f78d3e8de7a37b93870af6ff..0f50f6d763257b85b21685b249d06590dbd5c11d 100644 (file)
@@ -1089,3 +1089,25 @@ void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num)
                gicd_set_ispendr(gicv3_driver_data->gicd_base, id);
        }
 }
+
+/*******************************************************************************
+ * This function sets the PMR register with the supplied value. Returns the
+ * original PMR.
+ ******************************************************************************/
+unsigned int gicv3_set_pmr(unsigned int mask)
+{
+       unsigned int old_mask;
+
+       old_mask = read_icc_pmr_el1();
+
+       /*
+        * Order memory updates w.r.t. PMR write, and ensure they're visible
+        * before potential out of band interrupt trigger because of PMR update.
+        * PMR system register writes are self-synchronizing, so no ISB required
+        * thereafter.
+        */
+       dsbishst();
+       write_icc_pmr_el1(mask);
+
+       return old_mask;
+}
index bc2822ee1d9ca503cdbe364d4e98f9d8fbc7ed75..9b8510aabeee91c73c7a16b704a845e3948ed2ab 100644 (file)
@@ -174,6 +174,7 @@ void gicv2_raise_sgi(int sgi_num, int proc_num);
 void gicv2_set_spi_routing(unsigned int id, int proc_num);
 void gicv2_set_interrupt_pending(unsigned int id);
 void gicv2_clear_interrupt_pending(unsigned int id);
+unsigned int gicv2_set_pmr(unsigned int mask);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV2_H__ */
index 09d6d808481c19bad0f5ef60defa73d4f7ff77c7..95b6e3bb9bd6946087a864d5ac63b971d5b64883 100644 (file)
@@ -389,6 +389,7 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm,
                u_register_t mpidr);
 void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num);
 void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num);
+unsigned int gicv3_set_pmr(unsigned int mask);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV3_H__ */
index c8caea28678d07b871597a5a3e1e3d8572dd932f..469e9b0d05a5a7f6ba7b80e4571368c0f5e11f9c 100644 (file)
@@ -213,6 +213,7 @@ DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
 DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
+DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
 DEFINE_SYSOP_FUNC(isb)
 
 void __dead2 smc(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3,
index b880497ce618dd572e2c7d31cfce0f6317bdb559..03110fd5a8f452057261a456e284ef186e95351a 100644 (file)
@@ -204,6 +204,7 @@ DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
 DEFINE_SYSOP_TYPE_FUNC(dmb, ish)
+DEFINE_SYSOP_TYPE_FUNC(dmb, ishst)
 DEFINE_SYSOP_FUNC(isb)
 
 uint32_t get_afflvl_shift(uint32_t);
index ab5d68ed5c614438d6cb564111895f91aea90814..f03a3997af9a284ff6ae8e095314c3716277f484 100644 (file)
@@ -87,6 +87,7 @@ void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
                u_register_t mpidr);
 void plat_ic_set_interrupt_pending(unsigned int id);
 void plat_ic_clear_interrupt_pending(unsigned int id);
+unsigned int plat_ic_set_priority_mask(unsigned int mask);
 
 /*******************************************************************************
  * Optional common functions (may be overridden)
index 646049489e2c628cb54be6b0e6cd4ab1461adc90..05fabcab1d91d430c08f3b9f44b9313cb47a9184 100644 (file)
@@ -272,3 +272,8 @@ void plat_ic_clear_interrupt_pending(unsigned int id)
 {
        gicv2_clear_interrupt_pending(id);
 }
+
+unsigned int plat_ic_set_priority_mask(unsigned int mask)
+{
+       return gicv2_set_pmr(mask);
+}
index e5bf014d2800a69e01ce666e8ef4761e0f2110c2..52ceb6a7ca45dc9154d664396d39c769d18e9c9f 100644 (file)
@@ -266,6 +266,11 @@ void plat_ic_clear_interrupt_pending(unsigned int id)
        assert(id >= MIN_PPI_ID);
        gicv3_clear_interrupt_pending(id, plat_my_core_pos());
 }
+
+unsigned int plat_ic_set_priority_mask(unsigned int mask)
+{
+       return gicv3_set_pmr(mask);
+}
 #endif
 #ifdef IMAGE_BL32