Merge "feat(versal): update macro name to generic and move to common place" into integration
diff --git a/docs/about/features.rst b/docs/about/features.rst
index 4b7fbe5..cb8b552 100644
--- a/docs/about/features.rst
+++ b/docs/about/features.rst
@@ -46,8 +46,8 @@
- A Test SP and SPD to demonstrate AArch64 Secure Monitor functionality and SP
interaction with PSCI.
-- SPDs for the `OP-TEE Secure OS`_, `NVIDIA Trusted Little Kernel`_
- and `Trusty Secure OS`_.
+- SPDs for the `OP-TEE Secure OS`_, `NVIDIA Trusted Little Kernel`_,
+ `Trusty Secure OS`_ and `ProvenCore Secure OS`_.
- A Trusted Board Boot implementation, conforming to all mandatory TBBR
requirements. This includes image authentication, Firmware Update (or
@@ -121,6 +121,7 @@
.. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os
.. _NVIDIA Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary
.. _Trusty Secure OS: https://source.android.com/security/trusty
+.. _ProvenCore Secure OS: https://provenrun.com/products/provencore/
--------------
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 96a0523..d86bd8a 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -772,6 +772,13 @@
:|F|: bl32/tsp/
:|F|: services/spd/tspd/
+ProvenCore Secure Payload Dispatcher
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Jérémie Corbier <jeremie.corbier@provenrun.com>
+:|G|: `jcorbier`_
+:|F|: docs/components/spd/pnc-dispatcher.rst
+:|F|: services/spd/pncd/
+
Tools
~~~~~
@@ -842,6 +849,7 @@
.. _grandpaul: https://github.com/grandpaul
.. _hzhuang1: https://github.com/hzhuang1
.. _JackyBai: https://github.com/JackyBai
+.. _jcorbier: https://github.com/jcorbier
.. _jenswi-linaro: https://github.com/jenswi-linaro
.. _jwerner-chromium: https://github.com/jwerner-chromium
.. _kostapr: https://github.com/kostapr
diff --git a/docs/components/spd/index.rst b/docs/components/spd/index.rst
index 25d0124..6857806 100644
--- a/docs/components/spd/index.rst
+++ b/docs/components/spd/index.rst
@@ -8,3 +8,4 @@
optee-dispatcher
tlk-dispatcher
trusty-dispatcher
+ pnc-dispatcher
diff --git a/docs/components/spd/pnc-dispatcher.rst b/docs/components/spd/pnc-dispatcher.rst
new file mode 100644
index 0000000..5be2fc7
--- /dev/null
+++ b/docs/components/spd/pnc-dispatcher.rst
@@ -0,0 +1,10 @@
+ProvenCore Dispatcher
+=====================
+
+ProvenCore dispatcher (PnC-D) adds support for ProvenRun's ProvenCore micro-kernel
+to work with Trusted Firmware-A (TF-A).
+
+ProvenCore is a secure OS developed by ProvenRun S.A.S. using deductive formal methods.
+
+Once a BL32 is ready, PnC-D can be included in the image by adding "SPD=pncd"
+to the build command.
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 5bf6fb3..3477a04 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -484,6 +484,10 @@
Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU
and is fixed in r2p1.
+- ``ERRATA_A710_2216384``: This applies errata 2216384 workaround to
+ Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
+ of the CPU and is fixed in r2p1.
+
- ``ERRATA_A710_2282622``: This applies errata 2282622 workaround to
Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
of the CPU and is fixed in r2p1.
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 339ebbe..afe89b9 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -152,6 +152,11 @@
to select the appropriate platform variant for the build. The range of
valid values is platform specific.
+- ``CSS_SYSTEM_GRACEFUL_RESET``: Build option to enable graceful powerdown of
+ CPU core on reset. This build option can be used on CSS platforms that
+ require all the CPUs to execute the CPU specific power down sequence to
+ complete a warm reboot sequence in which only the CPUs are power cycled.
+
--------------
.. |FIP in a GPT image| image:: ../../resources/diagrams/FIP_in_a_GPT_image.png
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index 5de2604..9fe8b37 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <common/debug.h>
#include <drivers/arm/css/css_scp.h>
#include <drivers/arm/css/scmi.h>
+#include <lib/mmio.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/arm/css/common/css_pm.h>
#include <plat/common/platform.h>
@@ -286,15 +287,42 @@
return HW_OFF;
}
+/*
+ * Callback function to raise a SGI designated to trigger the CPU power down
+ * sequence on all the online secondary cores.
+ */
+static void css_raise_pwr_down_interrupt(u_register_t mpidr)
+{
+#if CSS_SYSTEM_GRACEFUL_RESET
+ plat_ic_raise_el3_sgi(CSS_CPU_PWR_DOWN_REQ_INTR, mpidr);
+#endif
+}
+
void __dead2 css_scp_system_off(int state)
{
int ret;
/*
+ * Before issuing the system power down command, set the trusted mailbox
+ * to 0. This will ensure that in the case of a warm/cold reset, the
+ * primary CPU executes from the cold boot sequence.
+ */
+ mmio_write_64(PLAT_ARM_TRUSTED_MAILBOX_BASE, 0U);
+
+ /*
+ * Send powerdown request to online secondary core(s)
+ */
+ ret = psci_stop_other_cores(0, css_raise_pwr_down_interrupt);
+ if (ret != PSCI_E_SUCCESS) {
+ ERROR("Failed to powerdown secondary core(s)\n");
+ }
+
+ /*
* Disable GIC CPU interface to prevent pending interrupt from waking
* up the AP from WFI.
*/
plat_arm_gic_cpuif_disable();
+ plat_arm_gic_redistif_off();
/*
* Issue SCMI command. First issue a graceful
@@ -309,6 +337,9 @@
state, ret);
panic();
}
+
+ /* Powerdown of primary core */
+ psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
wfi();
ERROR("CSS set power state: operation not handled.\n");
panic();
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index 939d097..1925a13 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -417,7 +418,7 @@
* The proc_num parameter must be the linear index of the target PE in the
* system.
******************************************************************************/
-void gicv2_raise_sgi(int sgi_num, int proc_num)
+void gicv2_raise_sgi(int sgi_num, bool ns, int proc_num)
{
unsigned int sgir_val, target;
@@ -437,7 +438,7 @@
target = driver_data->target_masks[proc_num];
assert(target != 0U);
- sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, sgi_num);
+ sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, ns, sgi_num);
/*
* Ensure that any shared variable updates depending on out of band
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index 5f42ad9..e85dbc1 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -97,16 +98,28 @@
spi_id_max = GIC600_SPI_ID_MIN;
}
- spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
- spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
-
switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
case IIDR_MODEL_ARM_GIC_600:
+ spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
+ spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
+
chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
spi_block_min,
spi_blocks);
break;
case IIDR_MODEL_ARM_GIC_700:
+ /* Calculate the SPI_ID_MIN value for ESPI */
+ if (spi_id_min >= GIC700_ESPI_ID_MIN) {
+ spi_block_min = ESPI_BLOCK_MIN_VALUE(spi_id_min);
+ spi_block_min += SPI_BLOCKS_VALUE(GIC700_SPI_ID_MIN,
+ GIC700_SPI_ID_MAX);
+ } else {
+ spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
+ }
+
+ /* Calculate the total number of blocks */
+ spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
+
chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
spi_block_min,
spi_blocks);
@@ -202,13 +215,104 @@
}
/*******************************************************************************
- * Intialize GIC-600 Multichip operation.
+ * Validates the GIC-700 Multichip data structure passed by the platform.
+ ******************************************************************************/
+static void gic700_multichip_validate_data(
+ struct gic600_multichip_data *multichip_data)
+{
+ unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
+ unsigned int multichip_spi_blocks = 0U, multichip_espi_blocks = 0U;
+
+ assert(multichip_data != NULL);
+
+ if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
+ ERROR("GIC-700 Multichip count (%u) should not exceed %u\n",
+ multichip_data->chip_count, GIC600_MAX_MULTICHIP);
+ panic();
+ }
+
+ for (i = 0U; i < multichip_data->chip_count; i++) {
+ spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
+ spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];
+
+ if ((spi_id_min == 0U) || (spi_id_max == 0U)) {
+ continue;
+ }
+
+ /* MIN SPI ID check */
+ if ((spi_id_min < GIC700_SPI_ID_MIN) ||
+ ((spi_id_min >= GIC700_SPI_ID_MAX) &&
+ (spi_id_min < GIC700_ESPI_ID_MIN))) {
+ ERROR("Invalid MIN SPI ID {%u} passed for "
+ "Chip %u\n", spi_id_min, i);
+ panic();
+ }
+
+ if ((spi_id_min > spi_id_max) ||
+ ((spi_id_max - spi_id_min + 1) % 32 != 0)) {
+ ERROR("Unaligned SPI IDs {%u, %u} passed for "
+ "Chip %u\n", spi_id_min,
+ spi_id_max, i);
+ panic();
+ }
+
+ /* ESPI IDs range check */
+ if ((spi_id_min >= GIC700_ESPI_ID_MIN) &&
+ (spi_id_max > GIC700_ESPI_ID_MAX)) {
+ ERROR("Invalid ESPI IDs {%u, %u} passed for "
+ "Chip %u\n", spi_id_min,
+ spi_id_max, i);
+ panic();
+
+ }
+
+ /* SPI IDs range check */
+ if (((spi_id_min < GIC700_SPI_ID_MAX) &&
+ (spi_id_max > GIC700_SPI_ID_MAX))) {
+ ERROR("Invalid SPI IDs {%u, %u} passed for "
+ "Chip %u\n", spi_id_min,
+ spi_id_max, i);
+ panic();
+ }
+
+ /* SPI IDs overlap check */
+ if (spi_id_max < GIC700_SPI_ID_MAX) {
+ blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
+ if ((multichip_spi_blocks & blocks_of_32) != 0) {
+ ERROR("SPI IDs of Chip %u overlapping\n", i);
+ panic();
+ }
+ multichip_spi_blocks |= blocks_of_32;
+ }
+
+ /* ESPI IDs overlap check */
+ if (spi_id_max > GIC700_ESPI_ID_MIN) {
+ blocks_of_32 = BLOCKS_OF_32(spi_id_min - GIC700_ESPI_ID_MIN,
+ spi_id_max - GIC700_ESPI_ID_MIN);
+ if ((multichip_espi_blocks & blocks_of_32) != 0) {
+ ERROR("SPI IDs of Chip %u overlapping\n", i);
+ panic();
+ }
+ multichip_espi_blocks |= blocks_of_32;
+ }
+ }
+}
+
+/*******************************************************************************
+ * Intialize GIC-600 and GIC-700 Multichip operation.
******************************************************************************/
void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
{
unsigned int i;
+ uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
- gic600_multichip_validate_data(multichip_data);
+ if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
+ gic600_multichip_validate_data(multichip_data);
+ }
+
+ if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700) {
+ gic700_multichip_validate_data(multichip_data);
+ }
/*
* Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index 5d1ff6a..c7b15c1 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -41,6 +41,11 @@
#define GIC600_SPI_ID_MIN 32
#define GIC600_SPI_ID_MAX 960
+#define GIC700_SPI_ID_MIN 32
+#define GIC700_SPI_ID_MAX 991
+#define GIC700_ESPI_ID_MIN 4096
+#define GIC700_ESPI_ID_MAX 5119
+
/* Number of retries for PUP update */
#define GICD_PUP_UPDATE_RETRIES 10000
@@ -53,6 +58,9 @@
#define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \
(((spi_id_max) - (spi_id_min) + 1) / \
GIC600_SPI_ID_MIN)
+#define ESPI_BLOCK_MIN_VALUE(spi_id_min) \
+ (((spi_id_min) - GIC700_ESPI_ID_MIN + 1) / \
+ GIC700_SPI_ID_MIN)
#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \
(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 8ead43b..bc93f93 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -1095,11 +1095,12 @@
}
/*******************************************************************************
- * This function raises the specified Secure Group 0 SGI.
+ * This function raises the specified SGI of the specified group.
*
* The target parameter must be a valid MPIDR in the system.
******************************************************************************/
-void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target)
+void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group,
+ u_register_t target)
{
unsigned int tgt, aff3, aff2, aff1, aff0;
uint64_t sgi_val;
@@ -1129,7 +1130,22 @@
* interrupt trigger are observed before raising SGI.
*/
dsbishst();
- write_icc_sgi0r_el1(sgi_val);
+
+ switch (group) {
+ case GICV3_G0:
+ write_icc_sgi0r_el1(sgi_val);
+ break;
+ case GICV3_G1NS:
+ write_icc_asgi1r(sgi_val);
+ break;
+ case GICV3_G1S:
+ write_icc_sgi1r(sgi_val);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
isb();
}
diff --git a/fdts/morello-fvp.dts b/fdts/morello-fvp.dts
index 55c87bf..dc3df41 100644
--- a/fdts/morello-fvp.dts
+++ b/fdts/morello-fvp.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include "morello.dtsi"
/ {
+ model = "Arm Morello Fixed Virtual Platform";
chosen {
stdout-path = "serial0:115200n8";
@@ -78,16 +79,12 @@
/* The first bank of memory, memory map is actually provided by UEFI. */
memory@80000000 {
- #address-cells = <2>;
- #size-cells = <2>;
device_type = "memory";
/* [0x80000000-0xffffffff] */
reg = <0x00000000 0x80000000 0x0 0x80000000>;
};
memory@8080000000 {
- #address-cells = <2>;
- #size-cells = <2>;
device_type = "memory";
/* [0x8080000000-0x83ffffffff] */
reg = <0x00000080 0x80000000 0x1 0x80000000>;
@@ -143,8 +140,8 @@
scmi {
compatible = "arm,scmi";
mbox-names = "tx", "rx";
- mboxes = <&mailbox 1 0 &mailbox 1 1>;
- shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+ mboxes = <&mailbox 1 0>, <&mailbox 1 1>;
+ shmem = <&cpu_scp_hpri0>, <&cpu_scp_hpri1>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/fdts/morello-soc.dts b/fdts/morello-soc.dts
index 8464634..5f147b7 100644
--- a/fdts/morello-soc.dts
+++ b/fdts/morello-soc.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,9 +8,10 @@
#include "morello.dtsi"
/ {
+ model = "Arm Morello System Development Platform";
chosen {
- stdout-path = "soc_uart0:115200n8";
+ stdout-path = "serial0:115200n8";
};
reserved-memory {
@@ -59,16 +60,12 @@
/* The first bank of memory, memory map is actually provided by UEFI. */
memory@80000000 {
- #address-cells = <2>;
- #size-cells = <2>;
device_type = "memory";
/* [0x80000000-0xffffffff] */
reg = <0x00000000 0x80000000 0x0 0x7F000000>;
};
memory@8080000000 {
- #address-cells = <2>;
- #size-cells = <2>;
device_type = "memory";
/* [0x8080000000-0x83f7ffffff] */
reg = <0x00000080 0x80000000 0x3 0x78000000>;
@@ -78,10 +75,10 @@
compatible = "arm,smmu-v3";
reg = <0 0x4f400000 0 0x40000>;
interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 237 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
- interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+ <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
msi-parent = <&its2 0>;
#iommu-cells = <1>;
dma-coherent;
@@ -114,10 +111,10 @@
compatible = "arm,smmu-v3";
reg = <0 0x4f000000 0 0x40000>;
interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 41 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
- interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+ <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
msi-parent = <&its1 0>;
#iommu-cells = <1>;
dma-coherent;
@@ -150,16 +147,16 @@
compatible = "arm,smmu-v3";
reg = <0 0x2ce00000 0 0x40000>;
interrupts = <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>;
- interrupt-names = "eventq", "cmdq-sync", "gerror";
+ <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "cmdq-sync";
#iommu-cells = <1>;
};
dp0: display@2cc00000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "arm,mali-d32";
+ compatible = "arm,mali-d32", "arm,mali-d71";
reg = <0 0x2cc00000 0 0x20000>;
interrupts = <0 69 4>;
interrupt-names = "DPU";
@@ -220,8 +217,8 @@
scmi {
compatible = "arm,scmi";
mbox-names = "tx", "rx";
- mboxes = <&mailbox 1 0 &mailbox 1 1>;
- shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+ mboxes = <&mailbox 1 0>, <&mailbox 1 1>;
+ shmem = <&cpu_scp_hpri0>, <&cpu_scp_hpri1>;
#address-cells = <1>;
#size-cells = <0>;
scmi_dvfs: protocol@13 {
@@ -241,28 +238,28 @@
<0x0 0x300c0000 0 0x80000>; /* GICR */
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
- its1: its@30040000 {
+ its1: msi-controller@30040000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x30040000 0x0 0x20000>;
};
- its2: its@30060000 {
+ its2: msi-controller@30060000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x30060000 0x0 0x20000>;
};
- its_ccix: its@30080000 {
+ its_ccix: msi-controller@30080000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
reg = <0x0 0x30080000 0x0 0x20000>;
};
- its_pcie: its@300a0000 {
+ its_pcie: msi-controller@300a0000 {
compatible = "arm,gic-v3-its";
msi-controller;
#msi-cells = <1>;
diff --git a/fdts/morello.dtsi b/fdts/morello.dtsi
index f119820..20640c5 100644
--- a/fdts/morello.dtsi
+++ b/fdts/morello.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,7 +18,7 @@
};
gic: interrupt-controller@2c010000 {
- compatible = "arm,gic-600", "arm,gic-v3";
+ compatible = "arm,gic-v3";
#address-cells = <2>;
#interrupt-cells = <3>;
#size-cells = <2>;
@@ -70,12 +70,12 @@
#size-cells = <1>;
ranges = <0 0x0 0x06000000 0x8000>;
- cpu_scp_hpri0: scp-shmem@0 {
+ cpu_scp_hpri0: scp-sram@0 {
compatible = "arm,scmi-shmem";
reg = <0x0 0x80>;
};
- cpu_scp_hpri1: scp-shmem@80 {
+ cpu_scp_hpri1: scp-sram@80 {
compatible = "arm,scmi-shmem";
reg = <0x80 0x80>;
};
@@ -95,7 +95,7 @@
clock-output-names = "uartclk";
};
- soc_uart0: uart@2a400000 {
+ soc_uart0: serial@2a400000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2a400000 0x0 0x1000>;
interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index 0330989..95d056f 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -282,6 +283,7 @@
DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1)
DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64)
+DEFINE_COPROCR_WRITE_FUNC_64(icc_asgi1r, ICC_ASGI1R_EL1_64)
DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR)
DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
@@ -402,6 +404,8 @@
#define read_ctr_el0() read_ctr()
#define write_icc_sgi0r_el1(_v) write64_icc_sgi0r_el1(_v)
+#define write_icc_sgi1r(_v) write64_icc_sgi1r(_v)
+#define write_icc_asgi1r(_v) write64_icc_asgi1r(_v)
#define read_daif() read_cpsr()
#define write_daif(flags) write_cpsr(flags)
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3a2a032..8d3e31d 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -79,6 +79,7 @@
******************************************************************************/
#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
#define ICC_SGI1R S3_0_C12_C11_5
+#define ICC_ASGI1R S3_0_C12_C11_6
#define ICC_SRE_EL1 S3_0_C12_C12_5
#define ICC_SRE_EL2 S3_4_C12_C9_5
#define ICC_SRE_EL3 S3_6_C12_C12_5
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 10b0a0b..8c61554 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -492,6 +492,7 @@
DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r, ICC_ASGI1R)
DEFINE_RENAME_SYSREG_READ_FUNC(amcfgr_el0, AMCFGR_EL0)
DEFINE_RENAME_SYSREG_READ_FUNC(amcgcr_el0, AMCGCR_EL0)
diff --git a/include/bl32/pnc/pnc.h b/include/bl32/pnc/pnc.h
new file mode 100644
index 0000000..03a3214
--- /dev/null
+++ b/include/bl32/pnc/pnc.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PNC_H__
+#define __PNC_H__
+
+#define SMC_YIELD 0xbf000000
+#define SMC_ACTION_FROM_S 0xbf000001
+#define SMC_GET_SHAREDMEM 0xbf000002
+#define SMC_CONFIG_SHAREDMEM 0xbf000003
+#define SMC_ACTION_FROM_NS 0xbf000004
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+void *pncd_context_switch_to(unsigned long security_state);
+int plat_pncd_setup(void);
+uintptr_t plat_pncd_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, void *cookie, void *handle,
+ u_register_t flags);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PNC_H__ */
diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h
index b960194..cfc168d 100644
--- a/include/drivers/arm/gicv2.h
+++ b/include/drivers/arm/gicv2.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -50,13 +51,15 @@
#define SGIR_TGTLSTFLT_MASK U(0x3)
#define SGIR_TGTLST_SHIFT 16
#define SGIR_TGTLST_MASK U(0xff)
+#define SGIR_NSATT (U(0x1) << 16)
#define SGIR_INTID_MASK ULL(0xf)
#define SGIR_TGT_SPECIFIC U(0)
-#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, intid) \
+#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, nsatt, intid) \
((((tgt_lst_flt) & SGIR_TGTLSTFLT_MASK) << SGIR_TGTLSTFLT_SHIFT) | \
(((tgt) & SGIR_TGTLST_MASK) << SGIR_TGTLST_SHIFT) | \
+ ((nsatt) ? SGIR_NSATT : U(0)) | \
((intid) & SGIR_INTID_MASK))
/*******************************************************************************
@@ -127,6 +130,7 @@
#ifndef __ASSEMBLER__
#include <cdefs.h>
+#include <stdbool.h>
#include <stdint.h>
#include <common/interrupt_props.h>
@@ -185,7 +189,7 @@
void gicv2_disable_interrupt(unsigned int id);
void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority);
void gicv2_set_interrupt_type(unsigned int id, unsigned int type);
-void gicv2_raise_sgi(int sgi_num, int proc_num);
+void gicv2_raise_sgi(int sgi_num, bool ns, 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);
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 8371dd5..5bb22fd 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -315,7 +315,7 @@
#define SGIR_IRM_SHIFT 40
#define SGIR_IRM_MASK ULL(0x1)
#define SGIR_AFF3_SHIFT 48
-#define SGIR_AFF_MASK ULL(0xf)
+#define SGIR_AFF_MASK ULL(0xff)
#define SGIR_IRM_TO_AFF U(0)
@@ -354,6 +354,12 @@
#include <drivers/arm/gic_common.h>
#include <lib/utils_def.h>
+typedef enum {
+ GICV3_G1S,
+ GICV3_G1NS,
+ GICV3_G0
+} gicv3_irq_group_t;
+
static inline uintptr_t gicv3_redist_size(uint64_t typer_val)
{
#if GIC_ENABLE_V4_EXTN
@@ -575,7 +581,8 @@
unsigned int priority);
void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
unsigned int type);
-void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target);
+void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group,
+ u_register_t target);
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);
diff --git a/include/lib/cpus/aarch64/cortex_a710.h b/include/lib/cpus/aarch64/cortex_a710.h
index 040f073..e33b9d5 100644
--- a/include/lib/cpus/aarch64/cortex_a710.h
+++ b/include/lib/cpus/aarch64/cortex_a710.h
@@ -42,6 +42,7 @@
******************************************************************************/
#define CORTEX_A710_CPUACTLR5_EL1 S3_0_C15_C8_0
#define CORTEX_A710_CPUACTLR5_EL1_BIT_13 (ULL(1) << 13)
+#define CORTEX_A710_CPUACTLR5_EL1_BIT_17 (ULL(1) << 17)
#define CORTEX_A710_CPUACTLR5_EL1_BIT_44 (ULL(1) << 44)
/*******************************************************************************
@@ -52,4 +53,12 @@
#define CPUECTLR2_EL1_PF_MODE_LSB U(11)
#define CPUECTLR2_EL1_PF_MODE_WIDTH U(4)
+/*******************************************************************************
+ * CPU Selected Instruction Private register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUPSELR_EL3 S3_6_C15_C8_0
+#define CORTEX_A710_CPUPCR_EL3 S3_6_C15_C8_1
+#define CORTEX_A710_CPUPOR_EL3 S3_6_C15_C8_2
+#define CORTEX_A710_CPUPMR_EL3 S3_6_C15_C8_3
+
#endif /* CORTEX_A710_H */
diff --git a/include/lib/psci/psci_lib.h b/include/lib/psci/psci_lib.h
index 43e2f96..3edc50b 100644
--- a/include/lib/psci/psci_lib.h
+++ b/include/lib/psci/psci_lib.h
@@ -92,6 +92,7 @@
int psci_stop_other_cores(unsigned int wait_ms,
void (*stop_func)(u_register_t mpidr));
bool psci_is_last_on_cpu_safe(void);
+void psci_pwrdown_cpu(unsigned int power_level);
#endif /* __ASSEMBLER__ */
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index e5357f5..84e6b38 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,9 @@
#include <lib/psci/psci.h>
+/* SGI used to trigger per-core power down request */
+#define CSS_CPU_PWR_DOWN_REQ_INTR ARM_IRQ_SEC_SGI_7
+
/* Macros to read the CSS power domain state */
#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0]
#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1]
@@ -37,6 +40,9 @@
void css_cpu_standby(plat_local_state_t cpu_state);
void css_get_sys_suspend_power_state(psci_power_state_t *req_state);
int css_node_hw_state(u_register_t mpidr, unsigned int power_level);
+void css_setup_cpu_pwr_down_intr(void);
+int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+ void *handle, void *cookie);
/*
* This mapping array has to be exported by the platform. Each element at
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 184606a..31607c2 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -104,6 +104,8 @@
void plat_ic_set_interrupt_type(unsigned int id, unsigned int type);
void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority);
void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target);
+void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target);
+void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target);
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);
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 0b06169..77f7a8d 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -312,6 +312,48 @@
endfunc check_errata_2147715
/* ---------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2216384.
+ * This applies to revision r0p0, r1p0 and r2p0.
+ * It is fixed in r2p1.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_a710_2216384_wa
+ /* Compare x0 against revision r2p0 */
+ mov x17, x30
+ bl check_errata_2216384
+ cbz x0, 1f
+
+ /* Apply workaround: set CPUACTLR5_EL1[17]
+ * to 1 and the following instruction
+ * patching sequence.
+ */
+ mrs x1, CORTEX_A710_CPUACTLR5_EL1
+ orr x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_17
+ msr CORTEX_A710_CPUACTLR5_EL1, x1
+
+ ldr x0,=0x5
+ msr CORTEX_A710_CPUPSELR_EL3, x0
+ ldr x0,=0x10F600E000
+ msr CORTEX_A710_CPUPOR_EL3, x0
+ ldr x0,=0x10FF80E000
+ msr CORTEX_A710_CPUPMR_EL3, x0
+ ldr x0,=0x80000000003FF
+ msr CORTEX_A710_CPUPCR_EL3, x0
+ isb
+1:
+ ret x17
+endfunc errata_a710_2216384_wa
+
+func check_errata_2216384
+ /* Applies to r0p0, r1p0 and r2p0 */
+ mov x1, #0x20
+ b cpu_rev_var_ls
+endfunc check_errata_2216384
+
+/* ---------------------------------------------------------------
* Errata Workaround for Cortex-A710 Erratum 2282622.
* This applies to revision r0p0, r1p0 and r2p0.
* It is fixed in r2p1.
@@ -470,6 +512,7 @@
report_errata ERRATA_A710_2282622, cortex_a710, 2282622
report_errata ERRATA_A710_2008768, cortex_a710, 2008768
report_errata ERRATA_A710_2147715, cortex_a710, 2147715
+ report_errata ERRATA_A710_2216384, cortex_a710, 2216384
report_errata ERRATA_A710_2371105, cortex_a710, 2371105
report_errata WORKAROUND_CVE_2022_23960, cortex_a710, cve_2022_23960
report_errata ERRATA_DSU_2313941, cortex_a710, dsu_2313941
@@ -537,6 +580,11 @@
bl errata_a710_2147715_wa
#endif
+#if ERRATA_A710_2216384
+ mov x0, x18
+ bl errata_a710_2216384_wa
+#endif /* ERRATA_A710_2216384 */
+
#if ERRATA_A710_2282622
mov x0, x18
bl errata_a710_2282622_wa
@@ -550,8 +598,8 @@
#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
/*
* The Cortex-A710 generic vectors are overridden to apply errata
- * mitigation on exception entry from lower ELs.
- */
+ * mitigation on exception entry from lower ELs.
+ */
adr x0, wa_cve_vbar_cortex_a710
msr vbar_el3, x0
#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index f8e2cbf..08871f8 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -536,6 +536,10 @@
# to revision r2p0 of the Cortex-A710 CPU and is fixed in revision r2p1.
ERRATA_A710_2147715 ?=0
+# Flag to apply erratum 2216384 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
+ERRATA_A710_2216384 ?=0
+
# Flag to apply erratum 2282622 workaround during reset. This erratum applies
# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
ERRATA_A710_2282622 ?=0
@@ -1132,6 +1136,10 @@
$(eval $(call assert_boolean,ERRATA_A710_2147715))
$(eval $(call add_define,ERRATA_A710_2147715))
+# Process ERRATA_A710_2216384 flag
+$(eval $(call assert_boolean,ERRATA_A710_2216384))
+$(eval $(call add_define,ERRATA_A710_2216384))
+
# Process ERRATA_A710_2282622 flag
$(eval $(call assert_boolean,ERRATA_A710_2282622))
$(eval $(call add_define,ERRATA_A710_2282622))
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 68aacc1..4355b12 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -229,14 +230,11 @@
sctlr_el2);
/*
- * The GICv3 driver initializes the ICC_SRE_EL2 register during
- * platform setup. Use the same setting for the corresponding
- * context register to make sure the correct bits are set when
- * restoring NS context.
+ * Program the ICC_SRE_EL2 to make sure the correct bits are set
+ * when restoring NS context.
*/
- u_register_t icc_sre_el2 = read_icc_sre_el2();
- icc_sre_el2 |= (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT);
- icc_sre_el2 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT);
+ u_register_t icc_sre_el2 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT |
+ ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT;
write_ctx_reg(get_el2_sysregs_ctx(ctx), CTX_ICC_SRE_EL2,
icc_sre_el2);
#endif /* CTX_INCLUDE_EL2_REGS */
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index b60ddbb..efcfed8 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -954,7 +954,7 @@
* Initiate power down sequence, by calling power down operations registered for
* this CPU.
******************************************************************************/
-void psci_do_pwrdown_sequence(unsigned int power_level)
+void psci_pwrdown_cpu(unsigned int power_level)
{
#if HW_ASSISTED_COHERENCY
/*
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index 5447045..637adb9 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -109,7 +109,7 @@
/*
* Arch. management. Initiate power down sequence.
*/
- psci_do_pwrdown_sequence(psci_find_max_off_lvl(&state_info));
+ psci_pwrdown_cpu(psci_find_max_off_lvl(&state_info));
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 61bd966..caade9c 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -296,7 +296,6 @@
void psci_print_power_domain_map(void);
unsigned int psci_is_last_on_cpu(void);
int psci_spd_migrate_info(u_register_t *mpidr);
-void psci_do_pwrdown_sequence(unsigned int power_level);
/*
* CPU power down is directly called only when HW_ASSISTED_COHERENCY is
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index ffe3a91..f71994d 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -124,7 +124,7 @@
* TODO : Introduce a mechanism to query the cache level to flush
* and the cpu-ops power down to perform from the platform.
*/
- psci_do_pwrdown_sequence(max_off_lvl);
+ psci_pwrdown_cpu(max_off_lvl);
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index 464a157..3474016 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -96,4 +96,8 @@
#define PLAT_ARM_GICR_BASE UL(0x301C0000)
#endif
+/* Interrupt priority level for shutdown/reboot */
+#define PLAT_REBOOT_PRI GIC_HIGHEST_SEC_PRIORITY
+#define PLAT_EHF_DESC EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_REBOOT_PRI)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index b882dc8..cfe4e28 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -24,6 +24,9 @@
GICV3_IMPL_GIC600_MULTICHIP := 1
endif
+override CSS_SYSTEM_GRACEFUL_RESET := 1
+override EL3_EXCEPTION_HANDLING := 1
+
include plat/arm/css/sgi/sgi-common.mk
RDN2_BASE = plat/arm/board/rdn2
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 2fbbe45..1e4851c 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -35,6 +35,7 @@
drivers/arm/css/scmi/scmi_common.c \
drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
drivers/arm/css/scmi/scmi_sys_pwr_proto.c \
+ drivers/delay_timer/delay_timer.c \
drivers/arm/css/scp/css_pm_scmi.c
endif
@@ -88,3 +89,9 @@
$(eval $(call assert_boolean,CSS_NON_SECURE_UART))
$(eval $(call add_define,CSS_NON_SECURE_UART))
+# Process CSS_SYSTEM_GRACEFUL_RESET flag
+# This build option can be used on CSS platforms that require all the CPUs
+# to execute the CPU specific power down sequence to complete a warm reboot
+# sequence in which only the CPUs are power cycled.
+CSS_SYSTEM_GRACEFUL_RESET := 0
+$(eval $(call add_define,CSS_SYSTEM_GRACEFUL_RESET))
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 926b8ec..9b2639c 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,10 +9,14 @@
#include <platform_def.h>
#include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
#include <common/debug.h>
#include <drivers/arm/css/css_scp.h>
#include <lib/cassert.h>
#include <plat/arm/common/plat_arm.h>
+
+#include <plat/common/platform.h>
+
#include <plat/arm/css/common/css_pm.h>
/* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
@@ -110,6 +114,9 @@
/* Enable the gic cpu interface */
plat_arm_gic_cpuif_enable();
+
+ /* Setup the CPU power down request interrupt for secondary core(s) */
+ css_setup_cpu_pwr_down_intr();
}
/*******************************************************************************
@@ -331,6 +338,52 @@
return arm_validate_power_state(power_state, output_state);
}
+/*
+ * Setup the SGI interrupt that will be used trigger the execution of power
+ * down sequence for all the secondary cores. This interrupt is setup to be
+ * handled in EL3 context at a priority defined by the platform.
+ */
+void css_setup_cpu_pwr_down_intr(void)
+{
+#if CSS_SYSTEM_GRACEFUL_RESET
+ plat_ic_set_interrupt_type(CSS_CPU_PWR_DOWN_REQ_INTR, INTR_TYPE_EL3);
+ plat_ic_set_interrupt_priority(CSS_CPU_PWR_DOWN_REQ_INTR,
+ PLAT_REBOOT_PRI);
+ plat_ic_enable_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+#endif
+}
+
+/*
+ * For a graceful shutdown/reboot, each CPU in the system should do their power
+ * down sequence. On a PSCI shutdown/reboot request, only one CPU gets an
+ * opportunity to do the powerdown sequence. To achieve graceful reset, of all
+ * cores in the system, the CPU gets the opportunity raise warm reboot SGI to
+ * rest of the CPUs which are online. Add handler for the reboot SGI where the
+ * rest of the CPU execute the powerdown sequence.
+ */
+int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+ void *handle, void *cookie)
+{
+ assert(intr_raw == CSS_CPU_PWR_DOWN_REQ_INTR);
+
+ /* Deactivate warm reboot SGI */
+ plat_ic_end_of_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt from waking
+ * up the AP from WFI.
+ */
+ plat_arm_gic_cpuif_disable();
+ plat_arm_gic_redistif_off();
+
+ psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
+
+ dmbsy();
+
+ wfi();
+ return 0;
+}
+
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform will take care of registering the handlers with PSCI.
diff --git a/plat/arm/css/common/sp_min/css_sp_min.mk b/plat/arm/css/common/sp_min/css_sp_min.mk
index 6523a16..ae489fd 100644
--- a/plat/arm/css/common/sp_min/css_sp_min.mk
+++ b/plat/arm/css/common/sp_min/css_sp_min.mk
@@ -15,6 +15,7 @@
else
BL32_SOURCES += drivers/arm/css/mhu/css_mhu_doorbell.c \
drivers/arm/css/scp/css_pm_scmi.c \
+ drivers/delay_timer/delay_timer.c \
drivers/arm/css/scmi/scmi_common.c \
drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
drivers/arm/css/scmi/scmi_sys_pwr_proto.c
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 99f2f20..7ef7e6f 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,8 +13,11 @@
#include <drivers/arm/css/css_mhu_doorbell.h>
#include <drivers/arm/css/scmi.h>
#include <plat/arm/common/plat_arm.h>
+
#include <plat/common/platform.h>
+#include <plat/arm/css/common/css_pm.h>
+
#include <sgi_ras.h>
#include <sgi_variant.h>
@@ -105,6 +108,15 @@
#if RAS_EXTENSION
sgi_ras_intr_handler_setup();
#endif
+
+ /* Configure the warm reboot SGI for primary core */
+ css_setup_cpu_pwr_down_intr();
+
+#if CSS_SYSTEM_GRACEFUL_RESET
+ /* Register priority level handlers for reboot */
+ ehf_register_priority_handler(PLAT_REBOOT_PRI,
+ css_reboot_interrupt_handler);
+#endif
}
const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c
index 4c76f1b..0f988dc 100644
--- a/plat/common/plat_gicv2.c
+++ b/plat/common/plat_gicv2.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,6 +35,8 @@
#pragma weak plat_ic_set_interrupt_priority
#pragma weak plat_ic_set_interrupt_type
#pragma weak plat_ic_raise_el3_sgi
+#pragma weak plat_ic_raise_ns_sgi
+#pragma weak plat_ic_raise_s_el1_sgi
#pragma weak plat_ic_set_spi_routing
/*
@@ -247,12 +250,44 @@
/* Verify that this is a secure SGI */
assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3);
- gicv2_raise_sgi(sgi_num, id);
+ gicv2_raise_sgi(sgi_num, false, id);
#else
assert(false);
#endif
}
+void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target)
+{
+ int id;
+
+ /* Target must be a valid MPIDR in the system */
+ id = plat_core_pos_by_mpidr(target);
+ assert(id >= 0);
+
+ /* Verify that this is a non-secure SGI */
+ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_NS);
+
+ gicv2_raise_sgi(sgi_num, true, id);
+}
+
+void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target)
+{
+#if GICV2_G0_FOR_EL3
+ assert(false);
+#else
+ int id;
+
+ /* Target must be a valid MPIDR in the system */
+ id = plat_core_pos_by_mpidr(target);
+ assert(id >= 0);
+
+ /* Verify that this is a secure EL1 SGI */
+ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_S_EL1);
+
+ gicv2_raise_sgi(sgi_num, false, id);
+#endif
+}
+
void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
u_register_t mpidr)
{
diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c
index 4a8a7ee..2c3a067 100644
--- a/plat/common/plat_gicv3.c
+++ b/plat/common/plat_gicv3.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -39,6 +40,8 @@
#pragma weak plat_ic_set_interrupt_priority
#pragma weak plat_ic_set_interrupt_type
#pragma weak plat_ic_raise_el3_sgi
+#pragma weak plat_ic_raise_ns_sgi
+#pragma weak plat_ic_raise_s_el1_sgi
#pragma weak plat_ic_set_spi_routing
#pragma weak plat_ic_set_interrupt_pending
#pragma weak plat_ic_clear_interrupt_pending
@@ -242,7 +245,31 @@
assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
INTR_TYPE_EL3);
- gicv3_raise_secure_g0_sgi((unsigned int)sgi_num, target);
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G0, target);
+}
+
+void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target)
+{
+ /* Target must be a valid MPIDR in the system */
+ assert(plat_core_pos_by_mpidr(target) >= 0);
+
+ /* Verify that this is a non-secure SGI */
+ assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
+ INTR_TYPE_NS);
+
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1NS, target);
+}
+
+void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target)
+{
+ /* Target must be a valid MPIDR in the system */
+ assert(plat_core_pos_by_mpidr(target) >= 0);
+
+ /* Verify that this is a secure EL1 SGI */
+ assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
+ INTR_TYPE_S_EL1);
+
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1S, target);
}
void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index 3892151..6e438c4 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -87,7 +87,7 @@
clk_disable(RTCAPB);
/* Generate an IT to core 1 */
- gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU);
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, false, STM32MP_SECONDARY_CPU);
return PSCI_E_SUCCESS;
}
diff --git a/plat/xilinx/common/include/pm_client.h b/plat/xilinx/common/include/pm_client.h
index dc012b7..eae1d98 100644
--- a/plat/xilinx/common/include/pm_client.h
+++ b/plat/xilinx/common/include/pm_client.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,9 +25,9 @@
/* Global variables to be set in pm_client.c */
extern const struct pm_proc *primary_proc;
-#ifndef VERSAL_PLATFORM
+#if defined(PLAT_zynqmp)
enum pm_ret_status pm_set_suspend_mode(uint32_t mode);
const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid);
-#endif
+#endif /* PLAT_zynqmp */
#endif /* PM_CLIENT_H */
diff --git a/plat/xilinx/common/include/pm_ipi.h b/plat/xilinx/common/include/pm_ipi.h
index 2d20b9f..8a15668 100644
--- a/plat/xilinx/common/include/pm_ipi.h
+++ b/plat/xilinx/common/include/pm_ipi.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +10,7 @@
#define PM_IPI_H
#include <plat_ipi.h>
+#include <stddef.h>
#include "pm_common.h"
#define IPI_BLOCKING 1
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
index 2f52f38..318079b 100644
--- a/plat/xilinx/common/ipi.c
+++ b/plat/xilinx/common/ipi.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,7 +18,6 @@
#include <lib/mmio.h>
#include <ipi.h>
-#include <plat_ipi.h>
#include <plat_private.h>
/*********************************************************************
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 12313f2..9c9fd62 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +15,7 @@
#include <plat_private.h>
#include <plat/common/platform.h>
+#include "pm_defs.h"
#include "pm_ipi.h"
#define ERROR_CODE_MASK 0xFFFFU
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 349b856..9b36208 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -184,8 +184,9 @@
}
}
- if (handler != NULL)
- handler(intr_id, flags, handle, cookie);
+ if (handler != NULL) {
+ return handler(intr_id, flags, handle, cookie);
+ }
return 0;
}
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index ecd8d08..db9fae4 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -17,7 +17,6 @@
#include "pm_client.h"
#include "pm_defs.h"
#include "pm_svc_main.h"
-#include "../drivers/arm/gic/v3/gicv3_private.h"
/* default shutdown/reboot scope is system(2) */
static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
@@ -466,8 +465,6 @@
if (ret != 0) {
return PM_RET_ERROR_ARGS;
}
- gicd_write_irouter(gicv3_driver_data->gicd_base,
- (uint32_t)PLAT_VERSAL_IPI_IRQ, MODE);
ret = PM_RET_SUCCESS;
break;
default:
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index e2a3cf8..c539aa7 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -17,7 +17,6 @@
#define LIBPM_MODULE_ID 0x2U
#define LOADER_MODULE_ID 0x7U
-#define MODE 0x80000000U
#define MODULE_ID_MASK 0x0000ff00U
/**********************************************************
* PM API function declarations
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 950d495..48888e4 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -19,6 +19,9 @@
#include "pm_client.h"
#include "pm_ipi.h"
#include <drivers/arm/gicv3.h>
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+#define MODE 0x80000000U
#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U
#define INVALID_SGI 0xFFU
@@ -139,6 +142,8 @@
if (ret != 0) {
WARN("BL31: registering IPI interrupt failed\n");
}
+
+ gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
return ret;
}
@@ -253,7 +258,7 @@
*
* These EEMI calls performs functionality that does not require
* IPI transaction. The handler ends in TF-A and returns requested data to
- * kernel from TF-A
+ * kernel from TF-A.
*/
static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
void *handle, uint32_t security_flag)
@@ -355,7 +360,7 @@
uint32_t api_id;
/* Handle case where PM wasn't initialized properly */
- if (!pm_up) {
+ if (pm_up == false) {
SMC_RET1(handle, SMC_UNK);
}
@@ -363,7 +368,7 @@
* Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
* if smc called is non secure
*/
- if (is_caller_non_secure(flags)) {
+ if (is_caller_non_secure(flags) != 0) {
security_flag = NON_SECURE_FLAG;
}
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 38ad32b..1d59537 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -176,7 +176,7 @@
/* Return if no device tree is detected */
if (fdt_check_header(dtb) != 0) {
- NOTICE("Can't read DT at 0x%p\n", dtb);
+ NOTICE("Can't read DT at %p\n", dtb);
return;
}
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index 66bbf30..c2d22c2 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -40,7 +40,7 @@
# define BL31_BASE U(0xfffea000)
# define BL31_LIMIT U(0x100000000)
#else
-# define BL31_BASE U(0xfff5a000)
+# define BL31_BASE U(0xfffe5000)
# define BL31_LIMIT U(0x100000000)
#endif
#else
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 877127b..428bed5 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -352,7 +352,7 @@
#define RESTART_SCOPE_SHIFT (3)
#define RESTART_SCOPE_MASK (0x3U << RESTART_SCOPE_SHIFT)
-/*AFI registers */
+/* AFI registers */
#define AFIFM6_WRCTRL U(13)
#define FABRIC_WIDTH U(3)
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index dd82bc0..05adbd0 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -1,5 +1,6 @@
#
# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+# Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -11,11 +12,20 @@
ZYNQMP_WDT_RESTART := 0
IPI_CRC_CHECK := 0
override RESET_TO_BL31 := 1
-override GICV2_G0_FOR_EL3 := 1
override WARMBOOT_ENABLE_DCACHE_EARLY := 1
EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
+# pncd SPD requires secure SGI to be handled at EL1
+ifeq (${SPD},pncd)
+ifeq (${ZYNQMP_WDT_RESTART},1)
+$(error "Error: ZYNQMP_WDT_RESTART and SPD=pncd are incompatible")
+endif
+override GICV2_G0_FOR_EL3 := 0
+else
+override GICV2_G0_FOR_EL3 := 1
+endif
+
# Do not enable SVE
ENABLE_SVE_FOR_NS := 0
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index f24387a..82da57c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -151,6 +151,8 @@
0xffffffff);
}
+ dsb();
+
spin_unlock(&inc_lock);
if (active_cores == 0) {
diff --git a/services/spd/pncd/pncd.mk b/services/spd/pncd/pncd.mk
new file mode 100644
index 0000000..0f8eb25
--- /dev/null
+++ b/services/spd/pncd/pncd.mk
@@ -0,0 +1,24 @@
+# Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+PNCD_DIR := services/spd/pncd
+SPD_INCLUDES := -Iinclude/bl32/pnc
+SPD_INCLUDES += -Iinclude/common/
+
+SPD_SOURCES := services/spd/pncd/pncd_common.c \
+ services/spd/pncd/pncd_helpers.S \
+ services/spd/pncd/pncd_main.c
+
+NEED_BL32 := yes
+
+# The following constants need to be defined:
+# - SPD_PNCD_NS_IRQ: IRQ number used to notify NS world when SMC_ACTION_FROM_S is received
+# - SPD_PNCD_S_IRQ: IRQ number used to notify S world when SMC_ACTION_FROM_NS is received
+$(eval $(call assert_numerics, SPD_PNCD_NS_IRQ SPD_PNCD_S_IRQ))
+
+$(eval $(call add_defines,\
+ $(sort \
+ SPD_PNCD_NS_IRQ \
+ SPD_PNCD_S_IRQ \
+)))
diff --git a/services/spd/pncd/pncd_common.c b/services/spd/pncd/pncd_common.c
new file mode 100644
index 0000000..6fdb629
--- /dev/null
+++ b/services/spd/pncd/pncd_common.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include "pncd_private.h"
+
+/*******************************************************************************
+ * Given a secure payload entrypoint info pointer, entry point PC & pointer to a
+ * context data structure, this function will initialize pnc context and entry
+ * point info for the secure payload
+ ******************************************************************************/
+void pncd_init_pnc_ep_state(struct entry_point_info *pnc_entry_point,
+ uint64_t pc,
+ pnc_context_t *pnc_ctx)
+{
+ uint32_t ep_attr;
+
+ /* Passing a NULL context is a critical programming error */
+ assert(pnc_ctx);
+ assert(pnc_entry_point);
+ assert(pc);
+
+ /* Associate this context with the current cpu */
+ pnc_ctx->mpidr = read_mpidr();
+
+ cm_set_context(&pnc_ctx->cpu_ctx, SECURE);
+
+ /* initialise an entrypoint to set up the CPU context */
+ ep_attr = SECURE | EP_ST_ENABLE;
+ if (read_sctlr_el3() & SCTLR_EE_BIT) {
+ ep_attr |= EP_EE_BIG;
+ }
+ SET_PARAM_HEAD(pnc_entry_point, PARAM_EP, VERSION_1, ep_attr);
+
+ pnc_entry_point->pc = pc;
+ pnc_entry_point->spsr = SPSR_64(MODE_EL1,
+ MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ memset(&pnc_entry_point->args, 0, sizeof(pnc_entry_point->args));
+}
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Applies the S-EL1 system register context from pnc_ctx->cpu_ctx.
+ * 2. Saves the current C runtime state (callee saved registers) on the stack
+ * frame and saves a reference to this state.
+ * 3. Calls el3_exit() so that the EL3 system and general purpose registers
+ * from the pnc_ctx->cpu_ctx are used to enter the secure payload image.
+ ******************************************************************************/
+uint64_t pncd_synchronous_sp_entry(pnc_context_t *pnc_ctx)
+{
+ assert(pnc_ctx != NULL);
+ assert(pnc_ctx->c_rt_ctx == 0U);
+
+ /* Apply the Secure EL1 system register context and switch to it */
+ assert(cm_get_context(SECURE) == &pnc_ctx->cpu_ctx);
+ cm_el1_sysregs_context_restore(SECURE);
+#if CTX_INCLUDE_FPREGS
+ fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
+#endif
+ cm_set_next_eret_context(SECURE);
+
+ return pncd_enter_sp(&pnc_ctx->c_rt_ctx);
+}
+
+
+/*******************************************************************************
+ * This function takes an SP context pointer and:
+ * 1. Saves the S-EL1 system register context tp pnc_ctx->cpu_ctx.
+ * 2. Restores the current C runtime state (callee saved registers) from the
+ * stack frame using the reference to this state saved in pncd_enter_sp().
+ * 3. It does not need to save any general purpose or EL3 system register state
+ * as the generic smc entry routine should have saved those.
+ ******************************************************************************/
+void pncd_synchronous_sp_exit(pnc_context_t *pnc_ctx, uint64_t ret)
+{
+ assert(pnc_ctx != NULL);
+ /* Save the Secure EL1 system register context */
+ assert(cm_get_context(SECURE) == &pnc_ctx->cpu_ctx);
+ cm_el1_sysregs_context_save(SECURE);
+#if CTX_INCLUDE_FPREGS
+ fpregs_context_save(get_fpregs_ctx(cm_get_context(SECURE)));
+#endif
+
+ assert(pnc_ctx->c_rt_ctx != 0);
+ pncd_exit_sp(pnc_ctx->c_rt_ctx, ret);
+
+ /* Should never reach here */
+ panic();
+}
diff --git a/services/spd/pncd/pncd_helpers.S b/services/spd/pncd/pncd_helpers.S
new file mode 100644
index 0000000..736b30f
--- /dev/null
+++ b/services/spd/pncd/pncd_helpers.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include "pncd_private.h"
+
+ .global pncd_enter_sp
+ /* ---------------------------------------------
+ * This function is called with SP_EL0 as stack.
+ * Here we stash our EL3 callee-saved registers
+ * on to the stack as a part of saving the C
+ * runtime and enter the secure payload.
+ * 'x0' contains a pointer to the memory where
+ * the address of the C runtime context is to be
+ * saved.
+ * ---------------------------------------------
+ */
+func pncd_enter_sp
+ /* Make space for the registers that we're going to save */
+ mov x3, sp
+ str x3, [x0, #0]
+ sub sp, sp, #PNCD_C_RT_CTX_SIZE
+
+ /* Save callee-saved registers on to the stack */
+ stp x19, x20, [sp, #PNCD_C_RT_CTX_X19]
+ stp x21, x22, [sp, #PNCD_C_RT_CTX_X21]
+ stp x23, x24, [sp, #PNCD_C_RT_CTX_X23]
+ stp x25, x26, [sp, #PNCD_C_RT_CTX_X25]
+ stp x27, x28, [sp, #PNCD_C_RT_CTX_X27]
+ stp x29, x30, [sp, #PNCD_C_RT_CTX_X29]
+
+ /* ---------------------------------------------
+ * Everything is setup now. el3_exit() will
+ * use the secure context to restore to the
+ * general purpose and EL3 system registers to
+ * ERET into the secure payload.
+ * ---------------------------------------------
+ */
+ b el3_exit
+endfunc pncd_enter_sp
+
+ /* ---------------------------------------------
+ * This function is called 'x0' pointing to a C
+ * runtime context saved in pncd_enter_sp(). It
+ * restores the saved registers and jumps to
+ * that runtime with 'x0' as the new sp. This
+ * destroys the C runtime context that had been
+ * built on the stack below the saved context by
+ * the caller. Later the second parameter 'x1'
+ * is passed as return value to the caller
+ * ---------------------------------------------
+ */
+ .global pncd_exit_sp
+func pncd_exit_sp
+ /* Restore the previous stack */
+ mov sp, x0
+
+ /* Restore callee-saved registers on to the stack */
+ ldp x19, x20, [x0, #(PNCD_C_RT_CTX_X19 - PNCD_C_RT_CTX_SIZE)]
+ ldp x21, x22, [x0, #(PNCD_C_RT_CTX_X21 - PNCD_C_RT_CTX_SIZE)]
+ ldp x23, x24, [x0, #(PNCD_C_RT_CTX_X23 - PNCD_C_RT_CTX_SIZE)]
+ ldp x25, x26, [x0, #(PNCD_C_RT_CTX_X25 - PNCD_C_RT_CTX_SIZE)]
+ ldp x27, x28, [x0, #(PNCD_C_RT_CTX_X27 - PNCD_C_RT_CTX_SIZE)]
+ ldp x29, x30, [x0, #(PNCD_C_RT_CTX_X29 - PNCD_C_RT_CTX_SIZE)]
+
+ /* ---------------------------------------------
+ * This should take us back to the instruction
+ * after the call to the last pncd_enter_sp().
+ * Place the second parameter to x0 so that the
+ * caller will see it as a return value from the
+ * original entry call
+ * ---------------------------------------------
+ */
+ mov x0, x1
+ ret
+endfunc pncd_exit_sp
diff --git a/services/spd/pncd/pncd_main.c b/services/spd/pncd/pncd_main.c
new file mode 100644
index 0000000..99c4aa1
--- /dev/null
+++ b/services/spd/pncd/pncd_main.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*******************************************************************************
+ * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a
+ * plug-in component to the Secure Monitor, registered as a runtime service. The
+ * SPD is expected to be a functional extension of the Secure Payload (SP) that
+ * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting
+ * the Trusted OS/Applications range to the dispatcher. The SPD will either
+ * handle the request locally or delegate it to the Secure Payload. It is also
+ * responsible for initialising and maintaining communication with the SP.
+ ******************************************************************************/
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <bl31/interrupt_mgmt.h>
+#include <bl_common.h>
+#include <common/debug.h>
+#include <common/ep_info.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#include <pnc.h>
+#include "pncd_private.h"
+#include <runtime_svc.h>
+#include <tools_share/uuid.h>
+
+/*******************************************************************************
+ * Structure to keep track of ProvenCore state
+ ******************************************************************************/
+static pnc_context_t pncd_sp_context;
+
+static bool ree_info;
+static uint64_t ree_base_addr;
+static uint64_t ree_length;
+static uint64_t ree_tag;
+
+static bool pnc_initialized;
+
+static spinlock_t smc_handler_lock;
+
+static int pncd_init(void);
+
+static void context_save(unsigned long security_state)
+{
+ assert(sec_state_is_valid(security_state));
+
+ cm_el1_sysregs_context_save((uint32_t) security_state);
+#if CTX_INCLUDE_FPREGS
+ fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state)));
+#endif
+}
+
+static void *context_restore(unsigned long security_state)
+{
+ void *handle;
+
+ assert(sec_state_is_valid(security_state));
+
+ /* Get a reference to the next context */
+ handle = cm_get_context((uint32_t) security_state);
+ assert(handle);
+
+ /* Restore state */
+ cm_el1_sysregs_context_restore((uint32_t) security_state);
+#if CTX_INCLUDE_FPREGS
+ fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state)));
+#endif
+
+ cm_set_next_eret_context((uint32_t) security_state);
+
+ return handle;
+}
+
+static uint64_t pncd_sel1_interrupt_handler(uint32_t id,
+ uint32_t flags, void *handle, void *cookie);
+
+/*******************************************************************************
+ * Switch context to the specified security state and return the targeted
+ * handle. Note that the context may remain unchanged if the switch is not
+ * allowed.
+ ******************************************************************************/
+void *pncd_context_switch_to(unsigned long security_state)
+{
+ unsigned long sec_state_from =
+ security_state == SECURE ? NON_SECURE : SECURE;
+
+ assert(sec_state_is_valid(security_state));
+
+ /* Check if this is the first world switch */
+ if (!pnc_initialized) {
+ int rc;
+ uint32_t flags;
+
+ assert(sec_state_from == SECURE);
+
+ INFO("PnC initialization done\n");
+
+ /*
+ * Register an interrupt handler for S-EL1 interrupts
+ * when generated during code executing in the
+ * non-secure state.
+ */
+ flags = 0U;
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+ pncd_sel1_interrupt_handler,
+ flags);
+ if (rc != 0) {
+ ERROR("Failed to register S-EL1 interrupt handler (%d)\n",
+ rc);
+ panic();
+ }
+
+ context_save(SECURE);
+
+ pnc_initialized = true;
+
+ /*
+ * Release the lock before restoring the EL3 context to
+ * bl31_main.
+ */
+ spin_unlock(&smc_handler_lock);
+
+ /*
+ * SP reports completion. The SPD must have initiated
+ * the original request through a synchronous entry
+ * into the SP. Jump back to the original C runtime
+ * context.
+ */
+ pncd_synchronous_sp_exit(&pncd_sp_context, (uint64_t) 0x0);
+
+ /* Unreachable */
+ ERROR("Returned from pncd_synchronous_sp_exit... Should not happen\n");
+ panic();
+ }
+
+ /* Check that the world switch is allowed */
+ if (read_mpidr() != pncd_sp_context.mpidr) {
+ if (sec_state_from == SECURE) {
+ /*
+ * Secure -> Non-Secure world switch initiated on a CPU where there
+ * should be no Trusted OS running
+ */
+ WARN("Secure to Non-Secure switch requested on CPU where ProvenCore is not supposed to be running...\n");
+ }
+
+ /*
+ * Secure or Non-Secure world wants to switch world but there is no Secure
+ * software on this core
+ */
+ return cm_get_context((uint32_t) sec_state_from);
+ }
+
+ context_save(sec_state_from);
+
+ return context_restore(security_state);
+}
+
+/*******************************************************************************
+ * This function is the handler registered for S-EL1 interrupts by the PNCD. It
+ * validates the interrupt and upon success arranges entry into the PNC at
+ * 'pnc_sel1_intr_entry()' for handling the interrupt.
+ ******************************************************************************/
+static uint64_t pncd_sel1_interrupt_handler(uint32_t id,
+ uint32_t flags,
+ void *handle,
+ void *cookie)
+{
+ /* Check the security state when the exception was generated */
+ assert(get_interrupt_src_ss(flags) == NON_SECURE);
+
+ /* Sanity check the pointer to this cpu's context */
+ assert(handle == cm_get_context(NON_SECURE));
+
+ /* switch to PnC */
+ handle = pncd_context_switch_to(SECURE);
+
+ assert(handle != NULL);
+
+ SMC_RET0(handle);
+}
+
+#pragma weak plat_pncd_setup
+int plat_pncd_setup(void)
+{
+ return 0;
+}
+
+/*******************************************************************************
+ * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
+ * (aarch32/aarch64) if not already known and initialises the context for entry
+ * into the SP for its initialisation.
+ ******************************************************************************/
+static int pncd_setup(void)
+{
+ entry_point_info_t *pnc_ep_info;
+
+ /*
+ * Get information about the Secure Payload (BL32) image. Its
+ * absence is a critical failure.
+ *
+ * TODO: Add support to conditionally include the SPD service
+ */
+ pnc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+ if (!pnc_ep_info) {
+ WARN("No PNC provided by BL2 boot loader, Booting device without PNC initialization. SMC`s destined for PNC will return SMC_UNK\n");
+ return 1;
+ }
+
+ /*
+ * If there's no valid entry point for SP, we return a non-zero value
+ * signalling failure initializing the service. We bail out without
+ * registering any handlers
+ */
+ if (!pnc_ep_info->pc) {
+ return 1;
+ }
+
+ pncd_init_pnc_ep_state(pnc_ep_info,
+ pnc_ep_info->pc,
+ &pncd_sp_context);
+
+ /*
+ * All PNCD initialization done. Now register our init function with
+ * BL31 for deferred invocation
+ */
+ bl31_register_bl32_init(&pncd_init);
+ bl31_set_next_image_type(NON_SECURE);
+
+ return plat_pncd_setup();
+}
+
+/*******************************************************************************
+ * This function passes control to the Secure Payload image (BL32) for the first
+ * time on the primary cpu after a cold boot. It assumes that a valid secure
+ * context has already been created by pncd_setup() which can be directly used.
+ * It also assumes that a valid non-secure context has been initialised by PSCI
+ * so it does not need to save and restore any non-secure state. This function
+ * performs a synchronous entry into the Secure payload. The SP passes control
+ * back to this routine through a SMC.
+ ******************************************************************************/
+static int32_t pncd_init(void)
+{
+ entry_point_info_t *pnc_entry_point;
+ uint64_t rc = 0;
+
+ /*
+ * Get information about the Secure Payload (BL32) image. Its
+ * absence is a critical failure.
+ */
+ pnc_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
+ assert(pnc_entry_point);
+
+ cm_init_my_context(pnc_entry_point);
+
+ /*
+ * Arrange for an entry into the test secure payload. It will be
+ * returned via PNC_ENTRY_DONE case
+ */
+ rc = pncd_synchronous_sp_entry(&pncd_sp_context);
+
+ /*
+ * If everything went well at this point, the return value should be 0.
+ */
+ return rc == 0;
+}
+
+#pragma weak plat_pncd_smc_handler
+/*******************************************************************************
+ * This function is responsible for handling the platform-specific SMCs in the
+ * Trusted OS/App range as defined in the SMC Calling Convention Document.
+ ******************************************************************************/
+uintptr_t plat_pncd_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ (void) smc_fid;
+ (void) x1;
+ (void) x2;
+ (void) x3;
+ (void) x4;
+ (void) cookie;
+ (void) flags;
+
+ SMC_RET1(handle, SMC_UNK);
+}
+
+/*******************************************************************************
+ * This function is responsible for handling all SMCs in the Trusted OS/App
+ * range as defined in the SMC Calling Convention Document. It is also
+ * responsible for communicating with the Secure payload to delegate work and
+ * return results back to the non-secure state. Lastly it will also return any
+ * information that the secure payload needs to do the work assigned to it.
+ *
+ * It should only be called with the smc_handler_lock held.
+ ******************************************************************************/
+static uintptr_t pncd_smc_handler_unsafe(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t ns;
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+
+ assert(ns != 0 || read_mpidr() == pncd_sp_context.mpidr);
+
+ switch (smc_fid) {
+ case SMC_CONFIG_SHAREDMEM:
+ if (ree_info) {
+ /* Do not Yield */
+ SMC_RET0(handle);
+ }
+
+ /*
+ * Fetch the physical base address (x1) and size (x2) of the
+ * shared memory allocated by the Non-Secure world. This memory
+ * will be used by PNC to communicate with the Non-Secure world.
+ * Verifying the validity of these values is up to the Trusted
+ * OS.
+ */
+ ree_base_addr = x1 | (x2 << 32);
+ ree_length = x3;
+ ree_tag = x4;
+
+ INFO("IN SMC_CONFIG_SHAREDMEM: addr=%lx, length=%lx, tag=%lx\n",
+ (unsigned long) ree_base_addr,
+ (unsigned long) ree_length,
+ (unsigned long) ree_tag);
+
+ if ((ree_base_addr % 0x200000) != 0) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ if ((ree_length % 0x200000) != 0) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ ree_info = true;
+
+ /* Do not Yield */
+ SMC_RET4(handle, 0, 0, 0, 0);
+
+ break;
+
+ case SMC_GET_SHAREDMEM:
+ if (ree_info) {
+ x1 = (1U << 16) | ree_tag;
+ x2 = ree_base_addr & 0xFFFFFFFF;
+ x3 = (ree_base_addr >> 32) & 0xFFFFFFFF;
+ x4 = ree_length & 0xFFFFFFFF;
+ SMC_RET4(handle, x1, x2, x3, x4);
+ } else {
+ SMC_RET4(handle, 0, 0, 0, 0);
+ }
+
+ break;
+
+ case SMC_ACTION_FROM_NS:
+ if (ns == 0) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ if (SPD_PNCD_S_IRQ < MIN_PPI_ID) {
+ plat_ic_raise_s_el1_sgi(SPD_PNCD_S_IRQ,
+ pncd_sp_context.mpidr);
+ } else {
+ plat_ic_set_interrupt_pending(SPD_PNCD_S_IRQ);
+ }
+
+ SMC_RET0(handle);
+
+ break;
+
+ case SMC_ACTION_FROM_S:
+ if (ns != 0) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ if (SPD_PNCD_NS_IRQ < MIN_PPI_ID) {
+ /*
+ * NS SGI is sent to the same core as the one running
+ * PNC
+ */
+ plat_ic_raise_ns_sgi(SPD_PNCD_NS_IRQ, read_mpidr());
+ } else {
+ plat_ic_set_interrupt_pending(SPD_PNCD_NS_IRQ);
+ }
+
+ SMC_RET0(handle);
+
+ break;
+
+ case SMC_YIELD:
+ assert(handle == cm_get_context(ns != 0 ? NON_SECURE : SECURE));
+ handle = pncd_context_switch_to(ns != 0 ? SECURE : NON_SECURE);
+
+ assert(handle != NULL);
+
+ SMC_RET0(handle);
+
+ break;
+
+ default:
+ INFO("Unknown smc: %x\n", smc_fid);
+ break;
+ }
+
+ return plat_pncd_smc_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+}
+
+static uintptr_t pncd_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uintptr_t ret;
+
+ /* SMC handling is serialized */
+ spin_lock(&smc_handler_lock);
+ ret = pncd_smc_handler_unsafe(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ spin_unlock(&smc_handler_lock);
+
+ return ret;
+}
+
+/* Define a SPD runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ pncd_fast,
+ OEN_TOS_START,
+ OEN_TOS_END,
+ SMC_TYPE_FAST,
+ pncd_setup,
+ pncd_smc_handler
+);
+
+/* Define a SPD runtime service descriptor for standard SMC calls */
+DECLARE_RT_SVC(
+ pncd_std,
+ OEN_TOS_START,
+ OEN_TOS_END,
+ SMC_TYPE_YIELD,
+ NULL,
+ pncd_smc_handler
+);
diff --git a/services/spd/pncd/pncd_private.h b/services/spd/pncd/pncd_private.h
new file mode 100644
index 0000000..8c9b634
--- /dev/null
+++ b/services/spd/pncd/pncd_private.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PNCD_PRIVATE_H__
+#define __PNCD_PRIVATE_H__
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER __ */
+
+#include <context.h>
+#ifndef __ASSEMBLER__
+#include <lib/cassert.h>
+#endif /* __ASSEMBLER __ */
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define PNCD_C_RT_CTX_X19 U(0x0)
+#define PNCD_C_RT_CTX_X20 U(0x8)
+#define PNCD_C_RT_CTX_X21 U(0x10)
+#define PNCD_C_RT_CTX_X22 U(0x18)
+#define PNCD_C_RT_CTX_X23 U(0x20)
+#define PNCD_C_RT_CTX_X24 U(0x28)
+#define PNCD_C_RT_CTX_X25 U(0x30)
+#define PNCD_C_RT_CTX_X26 U(0x38)
+#define PNCD_C_RT_CTX_X27 U(0x40)
+#define PNCD_C_RT_CTX_X28 U(0x48)
+#define PNCD_C_RT_CTX_X29 U(0x50)
+#define PNCD_C_RT_CTX_X30 U(0x58)
+#define PNCD_C_RT_CTX_SIZE U(0x60)
+#define PNCD_C_RT_CTX_ENTRIES (PNCD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLER__
+
+/* AArch64 callee saved general purpose register context structure. */
+DEFINE_REG_STRUCT(c_rt_regs, PNCD_C_RT_CTX_ENTRIES);
+
+/*
+ * Compile time assertion to ensure that both the compiler and linker
+ * have the same double word aligned view of the size of the C runtime
+ * register context.
+ */
+CASSERT(sizeof(c_rt_regs_t) == PNCD_C_RT_CTX_SIZE,
+ assert_spd_c_rt_regs_size_mismatch);
+
+/*******************************************************************************
+ * Structure which helps the SPD to maintain the per-cpu state of the SP.
+ * 'mpidr' - mpidr of the CPU running PNC
+ * 'c_rt_ctx' - stack address to restore C runtime context from after
+ * returning from a synchronous entry into the SP.
+ * 'cpu_ctx' - space to maintain SP architectural state
+ ******************************************************************************/
+typedef struct pnc_context {
+ uint64_t mpidr;
+ uint64_t c_rt_ctx;
+ cpu_context_t cpu_ctx;
+} pnc_context_t;
+
+/*******************************************************************************
+ * Function & Data prototypes
+ ******************************************************************************/
+uint64_t pncd_enter_sp(uint64_t *c_rt_ctx);
+void __dead2 pncd_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
+uint64_t pncd_synchronous_sp_entry(pnc_context_t *pnc_ctx);
+void __dead2 pncd_synchronous_sp_exit(pnc_context_t *pnc_ctx, uint64_t ret);
+void pncd_init_pnc_ep_state(struct entry_point_info *pnc_ep,
+ uint64_t pc,
+ pnc_context_t *pnc_ctx);
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PNCD_PRIVATE_H__ */
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index 814d051..c0beb65 100644
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -196,7 +196,7 @@
''' Generate arguments for the FIP Tool. '''
if "uuid" in sp_layout[sp]:
# Extract the UUID from the JSON file if the SP entry has a 'uuid' field
- uuid_std = uuid.UUID(data[key]['uuid'])
+ uuid_std = uuid.UUID(sp_layout[sp]['uuid'])
else:
with open(get_sp_manifest_full_path(sp_layout[sp], args), "r") as pm_f:
uuid_lines = [l for l in pm_f if 'uuid' in l]