Browse Source

plat/arm/fvp: Support performing SDEI platform setup in runtime

This patch introduces dynamic configuration for SDEI setup and is supported
when the new build flag SDEI_IN_FCONF is enabled. Instead of using C arrays
and processing the configuration at compile time, the config is moved to
dts files. It will be retrieved at runtime during SDEI init, using the fconf
layer.

Change-Id: If5c35a7517ba00a9f258d7f3e7c8c20cee169a31
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Co-authored-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
pull/1979/head
Balint Dobszay 5 years ago
committed by Madhukar Pappireddy
parent
commit
cbf9e84a19
  1. 8
      Makefile
  2. 5
      docs/getting_started/build-options.rst
  3. 26
      fdts/fvp-base-gicv3-psci-common.dtsi
  4. 8
      include/plat/arm/common/arm_def.h
  5. 31
      include/plat/arm/common/fconf_sdei_getter.h
  6. 1
      include/plat/common/platform.h
  7. 47
      include/services/sdei.h
  8. 56
      include/services/sdei_flags.h
  9. 5
      make_helpers/defaults.mk
  10. 5
      plat/arm/board/fvp/include/platform_def.h
  11. 47
      plat/arm/common/aarch64/arm_sdei.c
  12. 3
      plat/arm/common/arm_common.mk
  13. 103
      plat/arm/common/fconf/fconf_sdei_getter.c
  14. 10
      services/std_svc/sdei/sdei_main.c

8
Makefile

@ -651,6 +651,12 @@ ifeq ($(DYN_DISABLE_AUTH), 1)
endif
endif
# SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled.
ifeq ($(SDEI_SUPPORT)-$(SDEI_IN_FCONF),0-1)
$(error "SDEI_IN_FCONF is an experimental feature and is only supported when \
SDEI_SUPPORT is enabled")
endif
# If pointer authentication is used in the firmware, make sure that all the
# registers associated to it are also saved and restored.
# Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
@ -882,6 +888,7 @@ $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
$(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call assert_boolean,USE_DEBUGFS))
$(eval $(call assert_boolean,ARM_IO_IN_DTB))
$(eval $(call assert_boolean,SDEI_IN_FCONF))
$(eval $(call assert_boolean,USE_ROMLIB))
$(eval $(call assert_boolean,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
@ -961,6 +968,7 @@ $(eval $(call add_define,TRUSTED_BOARD_BOOT))
$(eval $(call add_define,USE_COHERENT_MEM))
$(eval $(call add_define,USE_DEBUGFS))
$(eval $(call add_define,ARM_IO_IN_DTB))
$(eval $(call add_define,SDEI_IN_FCONF))
$(eval $(call add_define,USE_ROMLIB))
$(eval $(call add_define,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))

5
docs/getting_started/build-options.rst

@ -645,6 +645,11 @@ Common build options
configuration device tree, instead of static structure in the code base.
This is currently an experimental feature.
- ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in
runtime using firmware configuration framework. The platform specific SDEI
shared and private events configuration is retrieved from device tree rather
than static C structures at compile time. This is currently an experimental
feature and is only supported if SDEI_SUPPORT build flag is enabled.
- ``USE_ROMLIB``: This flag determines whether library at ROM will be used.
This feature creates a library of functions to be placed in ROM and thus

26
fdts/fvp-base-gicv3-psci-common.dtsi

@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <services/sdei_flags.h>
/memreserve/ 0x80000000 0x00010000;
/ {
@ -36,6 +38,30 @@
max-pwr-lvl = <2>;
};
#if SDEI_IN_FCONF
firmware {
sdei {
compatible = "arm,sdei-1.0";
method = "smc";
private_event_count = <3>;
shared_event_count = <3>;
/*
* Each event descriptor has typically 3 fields:
* 1. Event number
* 2. Interrupt number the event is bound to or
* if event is dynamic, specified as SDEI_DYN_IRQ
* 3. Bit map of event flags
*/
private_events = <1000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
<1001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
<1002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>;
shared_events = <2000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
<2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
<2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>;
};
};
#endif /* SDEI_IN_FCONF */
cpus {
#address-cells = <2>;
#size-cells = <0>;

8
include/plat/arm/common/arm_def.h

@ -565,6 +565,13 @@
/* SGI used for SDEI signalling */
#define ARM_SDEI_SGI ARM_IRQ_SEC_SGI_0
#if SDEI_IN_FCONF
/* ARM SDEI dynamic private event max count */
#define ARM_SDEI_DP_EVENT_MAX_CNT 3
/* ARM SDEI dynamic shared event max count */
#define ARM_SDEI_DS_EVENT_MAX_CNT 3
#else
/* ARM SDEI dynamic private event numbers */
#define ARM_SDEI_DP_EVENT_0 1000
#define ARM_SDEI_DP_EVENT_1 1001
@ -585,5 +592,6 @@
SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \
SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
#endif /* SDEI_IN_FCONF */
#endif /* ARM_DEF_H */

31
include/plat/arm/common/fconf_sdei_getter.h

@ -0,0 +1,31 @@
/*
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FCONF_SDEI_GETTER_H
#define FCONF_SDEI_GETTER_H
#include <lib/fconf/fconf.h>
#include <platform_def.h>
#define sdei__dyn_config_getter(id) sdei_dyn_config.id
struct sdei_dyn_config_t {
uint32_t private_ev_cnt;
int32_t private_ev_nums[PLAT_SDEI_DP_EVENT_MAX_CNT];
unsigned int private_ev_intrs[PLAT_SDEI_DP_EVENT_MAX_CNT];
unsigned int private_ev_flags[PLAT_SDEI_DP_EVENT_MAX_CNT];
uint32_t shared_ev_cnt;
int32_t shared_ev_nums[PLAT_SDEI_DS_EVENT_MAX_CNT];
unsigned int shared_ev_intrs[PLAT_SDEI_DS_EVENT_MAX_CNT];
unsigned int shared_ev_flags[PLAT_SDEI_DS_EVENT_MAX_CNT];
};
int fconf_populate_sdei_dyn_config(uintptr_t config);
extern struct sdei_dyn_config_t sdei_dyn_config;
#endif /* FCONF_SDEI_GETTER_H */

1
include/plat/common/platform.h

@ -132,6 +132,7 @@ struct meminfo *bl1_plat_sec_mem_layout(void);
/* SDEI platform functions */
#if SDEI_SUPPORT
void plat_sdei_setup(void);
int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode);
void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr);
#endif

47
include/services/sdei.h

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -9,6 +9,7 @@
#include <lib/spinlock.h>
#include <lib/utils_def.h>
#include <services/sdei_flags.h>
/* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */
#define SDEI_VERSION 0xC4000020U
@ -41,50 +42,6 @@
#define SDEI_EV_HANDLED 0U
#define SDEI_EV_FAILED 1U
/* Internal: SDEI flag bit positions */
#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U
#define SDEI_MAPF_BOUND_SHIFT_ 2U
#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U
#define SDEI_MAPF_PRIVATE_SHIFT_ 4U
#define SDEI_MAPF_CRITICAL_SHIFT_ 5U
#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U
/* SDEI event 0 */
#define SDEI_EVENT_0 0
/* Placeholder interrupt for dynamic mapping */
#define SDEI_DYN_IRQ 0U
/* SDEI flags */
/*
* These flags determine whether or not an event can be associated with an
* interrupt. Static events are permanently associated with an interrupt, and
* can't be changed at runtime. Association of dynamic events with interrupts
* can be changed at run time using the SDEI_INTERRUPT_BIND and
* SDEI_INTERRUPT_RELEASE calls.
*
* SDEI_MAPF_DYNAMIC only indicates run time configurability, where as
* SDEI_MAPF_BOUND indicates interrupt association. For example:
*
* - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both
* SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set.
*
* - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither
* SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them.
*
* See also the is_map_bound() macro.
*/
#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_)
#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_)
#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_)
#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_)
#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_)
#define SDEI_MAPF_NORMAL 0
#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_)
/* Indices of private and shared mappings */
#define SDEI_MAP_IDX_PRIV_ 0U
#define SDEI_MAP_IDX_SHRD_ 1U

56
include/services/sdei_flags.h

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SDEI_FLAGS_H
#define SDEI_FLAGS_H
#include <lib/utils_def.h>
/* Internal: SDEI flag bit positions */
#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U
#define SDEI_MAPF_BOUND_SHIFT_ 2U
#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U
#define SDEI_MAPF_PRIVATE_SHIFT_ 4U
#define SDEI_MAPF_CRITICAL_SHIFT_ 5U
#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U
/* SDEI event 0 */
#define SDEI_EVENT_0 0
/* Placeholder interrupt for dynamic mapping */
#define SDEI_DYN_IRQ 0U
/* SDEI flags */
/*
* These flags determine whether or not an event can be associated with an
* interrupt. Static events are permanently associated with an interrupt, and
* can't be changed at runtime. Association of dynamic events with interrupts
* can be changed at run time using the SDEI_INTERRUPT_BIND and
* SDEI_INTERRUPT_RELEASE calls.
*
* SDEI_MAPF_DYNAMIC only indicates run time configurability, where as
* SDEI_MAPF_BOUND indicates interrupt association. For example:
*
* - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both
* SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set.
*
* - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither
* SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them.
*
* See also the is_map_bound() macro.
*/
#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_)
#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_)
#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_)
#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_)
#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_)
#define SDEI_MAPF_NORMAL 0
#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_)
#endif /* SDEI_FLAGS_H */

5
make_helpers/defaults.mk

@ -223,7 +223,10 @@ USE_COHERENT_MEM := 1
USE_DEBUGFS := 0
# Build option to fconf based io
ARM_IO_IN_DTB := 0
ARM_IO_IN_DTB := 0
# Build option to support SDEI through fconf
SDEI_IN_FCONF :=0
# Build option to choose whether Trusted Firmware uses library at ROM
USE_ROMLIB := 0

5
plat/arm/board/fvp/include/platform_def.h

@ -264,8 +264,13 @@
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
#if SDEI_IN_FCONF
#define PLAT_SDEI_DP_EVENT_MAX_CNT ARM_SDEI_DP_EVENT_MAX_CNT
#define PLAT_SDEI_DS_EVENT_MAX_CNT ARM_SDEI_DS_EVENT_MAX_CNT
#else
#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
#endif
#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
PLAT_SP_IMAGE_NS_BUF_SIZE)

47
plat/arm/common/aarch64/arm_sdei.c

@ -1,16 +1,51 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* SDEI configuration for ARM platforms */
#include <platform_def.h>
#include <bl31/ehf.h>
#include <common/debug.h>
#include <services/sdei.h>
#if SDEI_IN_FCONF
#include <plat/arm/common/fconf_sdei_getter.h>
#endif
#include <plat/common/platform.h>
#include <platform_def.h>
#if SDEI_IN_FCONF
/* Private event mappings */
static sdei_ev_map_t arm_sdei_private[PLAT_SDEI_DP_EVENT_MAX_CNT + 1] = { 0 };
/* Shared event mappings */
static sdei_ev_map_t arm_sdei_shared[PLAT_SDEI_DS_EVENT_MAX_CNT] = { 0 };
void plat_sdei_setup(void)
{
uint32_t i;
arm_sdei_private[0] = (sdei_ev_map_t)SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI);
for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_cnt); i++) {
arm_sdei_private[i + 1] = (sdei_ev_map_t)SDEI_PRIVATE_EVENT(
FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_nums[i]),
FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_intrs[i]),
FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_flags[i]));
}
for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_cnt); i++) {
arm_sdei_shared[i] = (sdei_ev_map_t)SDEI_SHARED_EVENT( \
FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_nums[i]),
FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_intrs[i]),
FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_flags[i]));
}
INFO("FCONF: SDEI platform setup\n");
}
#else
/* Private event mappings */
static sdei_ev_map_t arm_sdei_private[] = {
PLAT_ARM_PRIVATE_SDEI_EVENTS
@ -21,5 +56,11 @@ static sdei_ev_map_t arm_sdei_shared[] = {
PLAT_ARM_SHARED_SDEI_EVENTS
};
void plat_sdei_setup(void)
{
INFO("SDEI platform setup\n");
}
#endif /* SDEI_IN_FCONF */
/* Export ARM SDEI events */
REGISTER_SDEI_MAP(arm_sdei_private, arm_sdei_shared);

3
plat/arm/common/arm_common.mk

@ -263,6 +263,9 @@ endif
ifeq (${SDEI_SUPPORT},1)
BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c
ifeq (${SDEI_IN_FCONF},1)
BL31_SOURCES += plat/arm/common/fconf/fconf_sdei_getter.c
endif
endif
# RAS sources

103
plat/arm/common/fconf/fconf_sdei_getter.c

@ -0,0 +1,103 @@
/*
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <libfdt.h>
#include <plat/arm/common/fconf_sdei_getter.h>
#define PRIVATE_EVENT_NUM(i) private_events[3 * (i)]
#define PRIVATE_EVENT_INTR(i) private_events[3 * (i) + 1]
#define PRIVATE_EVENT_FLAGS(i) private_events[3 * (i) + 2]
#define SHARED_EVENT_NUM(i) shared_events[3 * (i)]
#define SHARED_EVENT_INTR(i) shared_events[3 * (i) + 1]
#define SHARED_EVENT_FLAGS(i) shared_events[3 * (i) + 2]
struct sdei_dyn_config_t sdei_dyn_config;
int fconf_populate_sdei_dyn_config(uintptr_t config)
{
uint32_t i;
int node, err;
uint32_t private_events[PLAT_SDEI_DP_EVENT_MAX_CNT * 3];
uint32_t shared_events[PLAT_SDEI_DS_EVENT_MAX_CNT * 3];
const void *dtb = (void *)config;
/* Check that the node offset points to compatible property */
node = fdt_node_offset_by_compatible(dtb, -1, "arm,sdei-1.0");
if (node < 0) {
ERROR("FCONF: Can't find 'arm,sdei-1.0' compatible node in dtb\n");
return node;
}
/* Read number of private mappings */
err = fdt_read_uint32(dtb, node, "private_event_count",
&sdei_dyn_config.private_ev_cnt);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'private_event_count': %u\n",
sdei_dyn_config.private_ev_cnt);
return err;
}
/* Check if the value is in range */
if (sdei_dyn_config.private_ev_cnt > PLAT_SDEI_DP_EVENT_MAX_CNT) {
ERROR("FCONF: Invalid value for 'private_event_count': %u\n",
sdei_dyn_config.private_ev_cnt);
return -1;
}
/* Read private mappings */
err = fdt_read_uint32_array(dtb, node, "private_events",
sdei_dyn_config.private_ev_cnt * 3, private_events);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'private_events': %d\n", err);
return err;
}
/* Move data to fconf struct */
for (i = 0; i < sdei_dyn_config.private_ev_cnt; i++) {
sdei_dyn_config.private_ev_nums[i] = PRIVATE_EVENT_NUM(i);
sdei_dyn_config.private_ev_intrs[i] = PRIVATE_EVENT_INTR(i);
sdei_dyn_config.private_ev_flags[i] = PRIVATE_EVENT_FLAGS(i);
}
/* Read number of shared mappings */
err = fdt_read_uint32(dtb, node, "shared_event_count",
&sdei_dyn_config.shared_ev_cnt);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'shared_event_count'\n");
return err;
}
/* Check if the value is in range */
if (sdei_dyn_config.shared_ev_cnt > PLAT_SDEI_DS_EVENT_MAX_CNT) {
ERROR("FCONF: Invalid value for 'shared_event_count': %u\n",
sdei_dyn_config.shared_ev_cnt);
return -1;
}
/* Read shared mappings */
err = fdt_read_uint32_array(dtb, node, "shared_events",
sdei_dyn_config.shared_ev_cnt * 3, shared_events);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'shared_events': %d\n", err);
return err;
}
/* Move data to fconf struct */
for (i = 0; i < sdei_dyn_config.shared_ev_cnt; i++) {
sdei_dyn_config.shared_ev_nums[i] = SHARED_EVENT_NUM(i);
sdei_dyn_config.shared_ev_intrs[i] = SHARED_EVENT_INTR(i);
sdei_dyn_config.shared_ev_flags[i] = SHARED_EVENT_FLAGS(i);
}
return 0;
}
FCONF_REGISTER_POPULATOR(HW_CONFIG, sdei, fconf_populate_sdei_dyn_config);

10
services/std_svc/sdei/sdei_main.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -226,6 +226,7 @@ static void sdei_class_init(sdei_class_t class)
/* SDEI dispatcher initialisation */
void sdei_init(void)
{
plat_sdei_setup();
sdei_class_init(SDEI_CRITICAL);
sdei_class_init(SDEI_NORMAL);
@ -328,8 +329,11 @@ finish:
}
/* Register handler and argument for an SDEI event */
static int64_t sdei_event_register(int ev_num, uint64_t ep, uint64_t arg,
uint64_t flags, uint64_t mpidr)
static int64_t sdei_event_register(int ev_num,
uint64_t ep,
uint64_t arg,
uint64_t flags,
uint64_t mpidr)
{
int ret;
unsigned int routing;

Loading…
Cancel
Save