Commit caf24c49 authored by Mark Dykes's avatar Mark Dykes Committed by TrustedFirmware Code Review
Browse files

Merge "plat/fvp: Add support for dynamic description of secure interrupts" into integration

parents 16af48e4 452d5e5e
...@@ -889,6 +889,7 @@ $(eval $(call assert_boolean,USE_COHERENT_MEM)) ...@@ -889,6 +889,7 @@ $(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call assert_boolean,USE_DEBUGFS)) $(eval $(call assert_boolean,USE_DEBUGFS))
$(eval $(call assert_boolean,ARM_IO_IN_DTB)) $(eval $(call assert_boolean,ARM_IO_IN_DTB))
$(eval $(call assert_boolean,SDEI_IN_FCONF)) $(eval $(call assert_boolean,SDEI_IN_FCONF))
$(eval $(call assert_boolean,SEC_INT_DESC_IN_FCONF))
$(eval $(call assert_boolean,USE_ROMLIB)) $(eval $(call assert_boolean,USE_ROMLIB))
$(eval $(call assert_boolean,USE_TBBR_DEFS)) $(eval $(call assert_boolean,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY)) $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
...@@ -969,6 +970,7 @@ $(eval $(call add_define,USE_COHERENT_MEM)) ...@@ -969,6 +970,7 @@ $(eval $(call add_define,USE_COHERENT_MEM))
$(eval $(call add_define,USE_DEBUGFS)) $(eval $(call add_define,USE_DEBUGFS))
$(eval $(call add_define,ARM_IO_IN_DTB)) $(eval $(call add_define,ARM_IO_IN_DTB))
$(eval $(call add_define,SDEI_IN_FCONF)) $(eval $(call add_define,SDEI_IN_FCONF))
$(eval $(call add_define,SEC_INT_DESC_IN_FCONF))
$(eval $(call add_define,USE_ROMLIB)) $(eval $(call add_define,USE_ROMLIB))
$(eval $(call add_define,USE_TBBR_DEFS)) $(eval $(call add_define,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY)) $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
......
...@@ -651,6 +651,12 @@ Common build options ...@@ -651,6 +651,12 @@ Common build options
than static C structures at compile time. This is currently an experimental than static C structures at compile time. This is currently an experimental
feature and is only supported if SDEI_SUPPORT build flag is enabled. feature and is only supported if SDEI_SUPPORT build flag is enabled.
- ``SEC_INT_DESC_IN_FCONF``: This flag determines whether to configure Group 0
and Group1 secure interrupts using the firmware configuration framework. The
platform specific secure interrupt property descriptor is retrieved from
device tree in runtime rather than depending on static C structure at compile
time. This is currently an experimental feature.
- ``USE_ROMLIB``: This flag determines whether library at ROM will be used. - ``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 This feature creates a library of functions to be placed in ROM and thus
reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
#include <services/sdei_flags.h> #include <services/sdei_flags.h>
#define LEVEL 0
#define EDGE 2
#define SDEI_NORMAL 0x70
#define HIGHEST_SEC 0
/memreserve/ 0x80000000 0x00010000; /memreserve/ 0x80000000 0x00010000;
/ { / {
...@@ -38,8 +43,9 @@ ...@@ -38,8 +43,9 @@
max-pwr-lvl = <2>; max-pwr-lvl = <2>;
}; };
#if SDEI_IN_FCONF #if SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF
firmware { firmware {
#if SDEI_IN_FCONF
sdei { sdei {
compatible = "arm,sdei-1.0"; compatible = "arm,sdei-1.0";
method = "smc"; method = "smc";
...@@ -59,9 +65,38 @@ ...@@ -59,9 +65,38 @@
<2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, <2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
<2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>; <2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>;
}; };
};
#endif /* SDEI_IN_FCONF */ #endif /* SDEI_IN_FCONF */
#if SEC_INT_DESC_IN_FCONF
sec_interrupts {
compatible = "arm,secure_interrupt_desc";
/* Number of G0 and G1 secure interrupts defined by the platform */
g0_intr_cnt = <2>;
g1s_intr_cnt = <9>;
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. Each interrupt property descriptor has 3 fields:
* 1. Interrupt number
* 2. Interrupt priority
* 3. Type of interrupt (Edge or Level configured)
*/
g0_intr_desc = < 8 SDEI_NORMAL EDGE>,
<14 HIGHEST_SEC EDGE>;
g1s_intr_desc = < 9 HIGHEST_SEC EDGE>,
<10 HIGHEST_SEC EDGE>,
<11 HIGHEST_SEC EDGE>,
<12 HIGHEST_SEC EDGE>,
<13 HIGHEST_SEC EDGE>,
<15 HIGHEST_SEC EDGE>,
<29 HIGHEST_SEC LEVEL>,
<56 HIGHEST_SEC LEVEL>,
<57 HIGHEST_SEC LEVEL>;
};
#endif /* SEC_INT_DESC_IN_FCONF */
};
#endif /* SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF */
cpus { cpus {
#address-cells = <2>; #address-cells = <2>;
#size-cells = <0>; #size-cells = <0>;
......
/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FCONF_SEC_INTR_CONFIG_H
#define FCONF_SEC_INTR_CONFIG_H
#include <lib/fconf/fconf.h>
#include <platform_def.h>
#define hw_config__sec_intr_prop_getter(id) sec_intr_prop.id
#define SEC_INT_COUNT_MAX U(15)
struct sec_intr_prop_t {
interrupt_prop_t descriptor[SEC_INT_COUNT_MAX];
uint32_t count;
};
int fconf_populate_sec_intr_config(uintptr_t config);
extern struct sec_intr_prop_t sec_intr_prop;
#endif /* FCONF_SEC_INTR_CONFIG_H */
...@@ -226,7 +226,10 @@ USE_DEBUGFS := 0 ...@@ -226,7 +226,10 @@ USE_DEBUGFS := 0
ARM_IO_IN_DTB := 0 ARM_IO_IN_DTB := 0
# Build option to support SDEI through fconf # Build option to support SDEI through fconf
SDEI_IN_FCONF :=0 SDEI_IN_FCONF := 0
# Build option to support Secure Interrupt descriptors through fconf
SEC_INT_DESC_IN_FCONF := 0
# Build option to choose whether Trusted Firmware uses library at ROM # Build option to choose whether Trusted Firmware uses library at ROM
USE_ROMLIB := 0 USE_ROMLIB := 0
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <fconf_hw_config_getter.h> #include <fconf_hw_config_getter.h>
#include <lib/utils.h> #include <lib/utils.h>
#include <plat/arm/common/plat_arm.h> #include <plat/arm/common/plat_arm.h>
#include <plat/arm/common/fconf_sec_intr_config.h>
#include <plat/common/platform.h> #include <plat/common/platform.h>
/* The GICv3 driver only needs to be initialized in EL3 */ /* The GICv3 driver only needs to be initialized in EL3 */
...@@ -23,10 +24,13 @@ static uint64_t fvp_gicr_base_addrs[2] = { 0U }; ...@@ -23,10 +24,13 @@ static uint64_t fvp_gicr_base_addrs[2] = { 0U };
/* List of zero terminated GICR frame addresses which CPUs will probe */ /* List of zero terminated GICR frame addresses which CPUs will probe */
static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs; static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs;
#if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \
(defined(__aarch64__) && defined(IMAGE_BL31))))
static const interrupt_prop_t fvp_interrupt_props[] = { static const interrupt_prop_t fvp_interrupt_props[] = {
PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
}; };
#endif
/* /*
* MPIDR hashing function for translating MPIDRs read from GICR_TYPER register * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
...@@ -52,8 +56,6 @@ static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr) ...@@ -52,8 +56,6 @@ static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr)
static gicv3_driver_data_t fvp_gic_data = { static gicv3_driver_data_t fvp_gic_data = {
.interrupt_props = fvp_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT, .rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = fvp_rdistif_base_addrs, .rdistif_base_addrs = fvp_rdistif_base_addrs,
.mpidr_to_core_pos = fvp_gicv3_mpidr_hash .mpidr_to_core_pos = fvp_gicv3_mpidr_hash
...@@ -61,7 +63,10 @@ static gicv3_driver_data_t fvp_gic_data = { ...@@ -61,7 +63,10 @@ static gicv3_driver_data_t fvp_gic_data = {
void plat_arm_gic_driver_init(void) void plat_arm_gic_driver_init(void)
{ {
/* Get GICD and GICR base addressed through FCONF APIs */ /*
* Get GICD and GICR base addressed through FCONF APIs.
* FCONF is not supported in BL32 for FVP.
*/
#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \ #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
(defined(__aarch64__) && defined(IMAGE_BL31)) (defined(__aarch64__) && defined(IMAGE_BL31))
fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config, fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
...@@ -69,9 +74,20 @@ void plat_arm_gic_driver_init(void) ...@@ -69,9 +74,20 @@ void plat_arm_gic_driver_init(void)
gicd_base); gicd_base);
fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config, fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config,
gicr_base); gicr_base);
#if SEC_INT_DESC_IN_FCONF
fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
sec_intr_prop, descriptor);
fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
sec_intr_prop, count);
#else
fvp_gic_data.interrupt_props = fvp_interrupt_props;
fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
#endif
#else #else
fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE; fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE; fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE;
fvp_gic_data.interrupt_props = fvp_interrupt_props;
fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
#endif #endif
/* /*
......
...@@ -221,6 +221,11 @@ ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),) ...@@ -221,6 +221,11 @@ ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
BL31_SOURCES += common/fdt_wrappers.c \ BL31_SOURCES += common/fdt_wrappers.c \
lib/fconf/fconf.c \ lib/fconf/fconf.c \
plat/arm/board/fvp/fconf/fconf_hw_config_getter.c plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
ifeq (${SEC_INT_DESC_IN_FCONF},1)
BL31_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
endif
endif endif
ifeq (${FVP_USE_SP804_TIMER},1) ifeq (${FVP_USE_SP804_TIMER},1)
......
...@@ -25,6 +25,11 @@ ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),) ...@@ -25,6 +25,11 @@ ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),)
BL32_SOURCES += common/fdt_wrappers.c \ BL32_SOURCES += common/fdt_wrappers.c \
lib/fconf/fconf.c \ lib/fconf/fconf.c \
plat/arm/board/fvp/fconf/fconf_hw_config_getter.c plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
ifeq (${SEC_INT_DESC_IN_FCONF},1)
BL32_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
endif
endif endif
include plat/arm/common/sp_min/arm_sp_min.mk include plat/arm/common/sp_min/arm_sp_min.mk
/*
* Copyright (c) 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_sec_intr_config.h>
#define G0_INTR_NUM(i) g0_intr_prop[3U * (i)]
#define G0_INTR_PRIORITY(i) g0_intr_prop[3U * (i) + 1]
#define G0_INTR_CONFIG(i) g0_intr_prop[3U * (i) + 2]
#define G1S_INTR_NUM(i) g1s_intr_prop[3U * (i)]
#define G1S_INTR_PRIORITY(i) g1s_intr_prop[3U * (i) + 1]
#define G1S_INTR_CONFIG(i) g1s_intr_prop[3U * (i) + 2]
struct sec_intr_prop_t sec_intr_prop;
static void print_intr_prop(interrupt_prop_t prop)
{
VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n",
prop.intr_num, prop.intr_pri, prop.intr_cfg);
}
int fconf_populate_sec_intr_config(uintptr_t config)
{
int node, err;
uint32_t g0_intr_count, g1s_intr_count;
uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3];
uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3];
/* Necessary to work with libfdt APIs */
const void *hw_config_dtb = (const void *)config;
node = fdt_node_offset_by_compatible(hw_config_dtb, -1,
"arm,secure_interrupt_desc");
if (node < 0) {
ERROR("FCONF: Unable to locate node with %s compatible property\n",
"arm,secure_interrupt_desc");
return node;
}
/* Read number of Group 0 interrupts specified by platform */
err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count);
if (err < 0) {
ERROR("FCONF: Could not locate g0s_intr_cnt property\n");
return err;
}
/* At least 1 Group 0 interrupt description has to be provided*/
if (g0_intr_count < 1U) {
ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n");
return -1;
}
/* Read number of Group 1 secure interrupts specified by platform */
err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt",
&g1s_intr_count);
if (err < 0) {
ERROR("FCONF: Could not locate g1s_intr_cnt property\n");
return err;
}
/* At least one Group 1 interrupt description has to be provided*/
if (g1s_intr_count < 1U) {
ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n");
return -1;
}
/*
* Check if the total number of secure interrupts described are within
* the limit defined statically by the platform.
*/
if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) {
ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n",
SEC_INT_COUNT_MAX);
return -1;
}
sec_intr_prop.count = g0_intr_count + g1s_intr_count;
/* Read the Group 0 interrupt descriptors */
err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc",
g0_intr_count * 3, g0_intr_prop);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err);
return err;
}
/* Read the Group 1 secure interrupt descriptors */
err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc",
g1s_intr_count * 3, g1s_intr_prop);
if (err < 0) {
ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err);
return err;
}
/* Populate Group 0 interrupt descriptors into fconf based C struct */
for (uint32_t i = 0; i < g0_intr_count; i++) {
interrupt_prop_t sec_intr_property;
/* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */
sec_intr_property.intr_grp = 1;
sec_intr_property.intr_num = G0_INTR_NUM(i);
sec_intr_property.intr_pri = G0_INTR_PRIORITY(i);
sec_intr_property.intr_cfg = G0_INTR_CONFIG(i);
sec_intr_prop.descriptor[i] = sec_intr_property;
print_intr_prop(sec_intr_property);
}
/* Populate G1 secure interrupt descriptors into fconf based C struct */
for (uint32_t i = 0; i < g1s_intr_count; i++) {
interrupt_prop_t sec_intr_property;
/* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */
sec_intr_property.intr_grp = 0;
sec_intr_property.intr_num = G1S_INTR_NUM(i);
sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i);
sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i);
sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property;
print_intr_prop(sec_intr_property);
}
return 0;
}
FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment