From d55a445069736e2652b44ddfeb9ea4d306796a0a Mon Sep 17 00:00:00 2001 From: Jeenu Viswambharan Date: Fri, 22 Sep 2017 08:32:09 +0100 Subject: GIC: Add API to set priority mask API documentation updated. Change-Id: I40feec1fe67a960d035061b54dd55610bc34ce1d Signed-off-by: Jeenu Viswambharan --- docs/platform-interrupt-controller-API.rst | 18 ++++++++++++++++++ drivers/arm/gic/v2/gicv2_main.c | 24 ++++++++++++++++++++++++ drivers/arm/gic/v3/gicv3_main.c | 22 ++++++++++++++++++++++ include/drivers/arm/gicv2.h | 1 + include/drivers/arm/gicv3.h | 1 + include/lib/aarch32/arch_helpers.h | 1 + include/lib/aarch64/arch_helpers.h | 1 + include/plat/common/platform.h | 1 + plat/common/plat_gicv2.c | 5 +++++ plat/common/plat_gicv3.c | 5 +++++ 10 files changed, 79 insertions(+) diff --git a/docs/platform-interrupt-controller-API.rst b/docs/platform-interrupt-controller-API.rst index d5c16733..795c0856 100644 --- a/docs/platform-interrupt-controller-API.rst +++ b/docs/platform-interrupt-controller-API.rst @@ -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.* diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index eab4c3bf..59b66323 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -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; +} diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 43dd77f1..0f50f6d7 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -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; +} diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h index bc2822ee..9b8510aa 100644 --- a/include/drivers/arm/gicv2.h +++ b/include/drivers/arm/gicv2.h @@ -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__ */ diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h index 09d6d808..95b6e3bb 100644 --- a/include/drivers/arm/gicv3.h +++ b/include/drivers/arm/gicv3.h @@ -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__ */ diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h index c8caea28..469e9b0d 100644 --- a/include/lib/aarch32/arch_helpers.h +++ b/include/lib/aarch32/arch_helpers.h @@ -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, diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index b880497c..03110fd5 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -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); diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index ab5d68ed..f03a3997 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -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) diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c index 64604948..05fabcab 100644 --- a/plat/common/plat_gicv2.c +++ b/plat/common/plat_gicv2.c @@ -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); +} diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c index e5bf014d..52ceb6a7 100644 --- a/plat/common/plat_gicv3.c +++ b/plat/common/plat_gicv3.c @@ -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 -- cgit v1.2.3