diff --git a/CHANGELOG.md b/CHANGELOG.md index 44f5f99b49b7c5fa2792fa30084e2e65b7aeaa79..0b42b334fab680edb83c9bb400d51b9ad902578e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +# OP-TEE - version 4.1.0 (2024-01-19) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_1], [commits][OP_TEE_optee_os_commits_4_1] and [pull requests][OP_TEE_optee_os_pr_4_1] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_1], [commits][OP_TEE_optee_client_commits_4_1] and [pull requests][OP_TEE_optee_client_pr_4_1] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_1], [commits][OP_TEE_optee_test_commits_4_1] and [pull requests][OP_TEE_optee_test_pr_4_1] + - OP-TEE/build: [release page][OP_TEE_build_release_4_1], [commits][OP_TEE_build_commits_4_1] and [pull requests][OP_TEE_build_pr_4_1] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_1], [commits][linaro_swg_optee_examples_commits_4_1] and [pull requests][linaro_swg_optee_examples_pr_4_1] + + +[OP_TEE_optee_os_release_4_1]: https://github.com/OP-TEE/optee_os/releases/tag/4.1.0 +[OP_TEE_optee_os_commits_4_1]: https://github.com/OP-TEE/optee_os/compare/4.0.0...4.1.0 +[OP_TEE_optee_os_pr_4_1]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_optee_client_release_4_1]: https://github.com/OP-TEE/optee_client/releases/tag/4.1.0 +[OP_TEE_optee_client_commits_4_1]: https://github.com/OP-TEE/optee_client/compare/4.0.0...4.1.0 +[OP_TEE_optee_client_pr_4_1]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_optee_test_release_4_1]: https://github.com/OP-TEE/optee_test/releases/tag/4.1.0 +[OP_TEE_optee_test_commits_4_1]: https://github.com/OP-TEE/optee_test/compare/4.0.0...4.1.0 +[OP_TEE_optee_test_pr_4_1]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_build_release_4_1]: https://github.com/OP-TEE/build/releases/tag/4.1.0 +[OP_TEE_build_commits_4_1]: https://github.com/OP-TEE/build/compare/4.0.0...4.1.0 +[OP_TEE_build_pr_4_1]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[linaro_swg_optee_examples_release_4_1]: https://github.com/linaro-swg/optee_examples/releases/tag/4.1.0 +[linaro_swg_optee_examples_commits_4_1]: https://github.com/linaro-swg/optee_examples/compare/4.0.0...4.1.0 +[linaro_swg_optee_examples_pr_4_1]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + # OP-TEE - version 4.0.0 (2023-10-20) - Links to the release pages, commits and pull requests merged into this release for: @@ -10,25 +40,25 @@ [OP_TEE_optee_os_release_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.0.0 [OP_TEE_optee_os_commits_4_0]: https://github.com/OP-TEE/optee_os/compare/3.22.0...4.0.0 -[OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20 +[OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_optee_client_release_4_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.0.0 [OP_TEE_optee_client_commits_4_0]: https://github.com/OP-TEE/optee_client/compare/3.22.0...4.0.0 -[OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20 +[OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_optee_test_release_4_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.0.0 [OP_TEE_optee_test_commits_4_0]: https://github.com/OP-TEE/optee_test/compare/3.22.0...4.0.0 -[OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20 +[OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_build_release_4_0]: https://github.com/OP-TEE/build/releases/tag/4.0.0 [OP_TEE_build_commits_4_0]: https://github.com/OP-TEE/build/compare/3.22.0...4.0.0 -[OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20 +[OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [linaro_swg_optee_examples_release_4_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.0.0 [linaro_swg_optee_examples_commits_4_0]: https://github.com/linaro-swg/optee_examples/compare/3.22.0...4.0.0 -[linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20 +[linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 -# OP-TEE - version 3.22 (2023-07-07) +# OP-TEE - version 3.22.0 (2023-07-07) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_22], [commits][OP_TEE_optee_os_commits_3_22] and [pull requests][OP_TEE_optee_os_pr_3_22] @@ -38,25 +68,25 @@ - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_22], [commits][linaro_swg_optee_examples_commits_3_22] and [pull requests][linaro_swg_optee_examples_pr_3_22] -[OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22 -[OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21...3.22 -[OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07 +[OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22.0 +[OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21.0...3.22.0 +[OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 -[OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22 -[OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21...3.22 -[OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07 +[OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22.0 +[OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21.0...3.22.0 +[OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 -[OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22 -[OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21...3.22 -[OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07 +[OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22.0 +[OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21.0...3.22.0 +[OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 -[OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22 -[OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21...3.22 -[OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07 +[OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22.0 +[OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21.0...3.22.0 +[OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 -[linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22 -[linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21...3.22 -[linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07 +[linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22.0 +[linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21.0...3.22.0 +[linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 # OP-TEE - version 3.21.0 (2023-04-14) diff --git a/MAINTAINERS b/MAINTAINERS index b4805295ec6225c573f2cd31d08c9a33ebb4f8e0..095165b2f032fc625d9cfaa1493a939ce48811fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -32,6 +32,11 @@ basis (R:). ---------- +AOSP build +R: Tadd Kao <tadd.kao@mediatek.com> [@taddk] +S: Maintained +F: mk/aosp_optee.mk + ARM Foundation FVP R: Jens Wiklander <jens.wiklander@linaro.org> [@jenswi-linaro] S: Maintained @@ -267,14 +272,25 @@ R: Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms] S: Maintained F: core/arch/arm/plat-stm/ +STMicroelectronics drivers +R: Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms] +R: Gatien Chevallier <gatien.chevallier@foss.st.com> [@GseoC] +S: Maintained +F: core/drivers/stm32_* + STMicroelectronics stm32mp1 R: Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms] S: Maintained F: core/arch/arm/plat-stm32mp1/ -F: core/drivers/stm32_* F: core/drivers/stm32mp15_huk.c F: core/drivers/stpmic1.c +STMicroelectronics stm32mp2 +R: Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms] +R: Gatien Chevallier <gatien.chevallier@foss.st.com> [@GseoC] +S: Maintained +F: core/arch/arm/plat-stm32mp2/* + Texas Instruments AM43xx, AM57xx, DRA7xx, AM65x, J721E, J784S4, AM64x, AM62x R: Andrew Davis <afd@ti.com> [@glneo] S: Maintained diff --git a/Makefile b/Makefile index 8db66780f52110e85ff9801ffe1cc76d45dae13c..8908849d50fbcdebc24ae314b05fd052e9324ebe 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,7 @@ clean: ${q}dirs="$(call cleandirs-for-rmdir)"; if [ "$$dirs" ]; then $(RMDIR) $$dirs; fi @if [ "$(out-dir)" != "$(O)" ]; then $(cmd-echo-silent) ' CLEAN $(O)'; fi ${q}if [ -d "$(O)" ]; then $(RMDIR) $(O); fi + ${q}rm -f compile_commands.json .PHONY: cscope cscope: diff --git a/core/arch/arm/arm.mk b/core/arch/arm/arm.mk index 706556b94128b07dd9738e5333306691a91070d8..34f5a633b3026cb16337558085663c9d116c938c 100644 --- a/core/arch/arm/arm.mk +++ b/core/arch/arm/arm.mk @@ -129,6 +129,9 @@ ifeq ($(CFG_CORE_FFA),y) ifneq ($(CFG_DT),y) $(error CFG_CORE_FFA depends on CFG_DT) endif +ifneq ($(CFG_ARM64_core),y) +$(error CFG_CORE_FFA depends on CFG_ARM64_core) +endif endif ifeq ($(CFG_CORE_PHYS_RELOCATABLE)-$(CFG_WITH_PAGER),y-y) @@ -179,7 +182,8 @@ CFG_SM_NO_CYCLE_COUNTING ?= y # CFG_CORE_ASYNC_NOTIF_GIC_INTID is defined by the platform to some free # interrupt. Setting it to a non-zero number enables support for using an # Arm-GIC to notify normal world. This config variable should use a value -# larger the 32 to make it of the type SPI. +# larger or equal to 24 to make it of the type SPI or PPI (secure PPI +# only). # Note that asynchronous notifactions must be enabled with # CFG_CORE_ASYNC_NOTIF=y for this variable to be used. CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 0 diff --git a/core/arch/arm/dts/sama5d2.dtsi b/core/arch/arm/dts/sama5d2.dtsi index 1a0429287a98a41edd9f57da899f06aa88221548..56c4dd5ca971b4154cba0d137e3e833bce3915ce 100644 --- a/core/arch/arm/dts/sama5d2.dtsi +++ b/core/arch/arm/dts/sama5d2.dtsi @@ -737,6 +737,16 @@ secure-status = "okay"; }; + sfc: sfc@f804c000 { + compatible = "atmel,sama5d2-sfc"; + reg = <0xf804c000 0x64>; + read-only; + status = "disabled"; + secure-status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + }; + i2s0: i2s@f8050000 { compatible = "atmel,sama5d2-i2s"; reg = <0xf8050000 0x100>; diff --git a/core/arch/arm/dts/stm32mp131.dtsi b/core/arch/arm/dts/stm32mp131.dtsi index fb13a53df5d953e0338a14fc1ea5e19890b41a57..3ddfaab8ce23365b2dd7779c4e43b44d7cb63f2c 100644 --- a/core/arch/arm/dts/stm32mp131.dtsi +++ b/core/arch/arm/dts/stm32mp131.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. */ @@ -83,6 +83,18 @@ }; + sdmmc1_io: sdmmc1_io { + compatible = "st,stm32mp13-iod"; + regulator-name = "sdmmc1_io"; + regulator-always-on; + }; + + sdmmc2_io: sdmmc2_io { + compatible = "st,stm32mp13-iod"; + regulator-name = "sdmmc2_io"; + regulator-always-on; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; diff --git a/core/arch/arm/dts/stm32mp135f-dk.dts b/core/arch/arm/dts/stm32mp135f-dk.dts index af22a610366418ecb4c3c68058845ef278ce4739..7357601bac99d47039438ab454f13ab51e15c28f 100644 --- a/core/arch/arm/dts/stm32mp135f-dk.dts +++ b/core/arch/arm/dts/stm32mp135f-dk.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. */ @@ -8,6 +8,7 @@ #include <dt-bindings/clock/stm32mp13-clksrc.h> #include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/gpio/stm32mp_gpio.h> #include <dt-bindings/regulator/st,stm32mp13-regulator.h> #include "stm32mp135.dtsi" #include "stm32mp13xf.dtsi" @@ -82,6 +83,18 @@ }; }; +&gpiob { + st,protreg = <TZPROT(9)>; +}; + +&gpiod { + st,protreg = <TZPROT(7)>; +}; + +&gpioe { + st,protreg = <TZPROT(15)>; +}; + &i2c4 { pinctrl-names = "default"; pinctrl-0 = <&i2c4_pins_a>; @@ -446,6 +459,14 @@ status = "okay"; }; +&sdmmc1_io { + vddsd1-supply = <&vdd>; +}; + +&sdmmc2_io { + vddsd2-supply = <&vdd>; +}; + &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_a>; diff --git a/core/arch/arm/dts/stm32mp151.dtsi b/core/arch/arm/dts/stm32mp151.dtsi index dce40957d7b1e185507fe7038cc249128dde76e8..d6729c8c1fd1e237e7269c0ed8f2f63260b60799 100644 --- a/core/arch/arm/dts/stm32mp151.dtsi +++ b/core/arch/arm/dts/stm32mp151.dtsi @@ -1839,8 +1839,8 @@ reg = <0x10000000 0x40000>, <0x30000000 0x40000>, <0x38000000 0x10000>; - resets = <&rcc MCU_R>; - st,syscfg-holdboot = <&rcc 0x10C 0x1>; + resets = <&rcc MCU_R>, <&rcc MCU_HOLD_BOOT_R>; + reset-names = "mcu_rst", "hold_boot"; st,syscfg-tz = <&rcc 0x000 0x1>; st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; diff --git a/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts new file mode 100644 index 0000000000000000000000000000000000000000..8236375389bf0e088aee2dd3eaa6fc8625e9b429 --- /dev/null +++ b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ + +/dts-v1/; + +#include "stm32mp157a-dk1.dts" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 SCMI Discovery Board"; + compatible = "st,stm32mp157a-dk1-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; diff --git a/core/arch/arm/dts/stm32mp157a-dk1.dts b/core/arch/arm/dts/stm32mp157a-dk1.dts index 7ba971e5b2a3fa2b621f0cd17efb57588754d1f4..294746da4ff279e66f3d390458ad777332cc190e 100644 --- a/core/arch/arm/dts/stm32mp157a-dk1.dts +++ b/core/arch/arm/dts/stm32mp157a-dk1.dts @@ -36,7 +36,3 @@ reg = <0xf0 0x10>; }; }; - -&rcc { - status = "okay"; -}; diff --git a/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts new file mode 100644 index 0000000000000000000000000000000000000000..e80e2a47c1e3ede6fe99bbc067b6596eea9aa737 --- /dev/null +++ b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ + +/dts-v1/; + +#include "stm32mp157c-dk2.dts" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 SCMI Discovery Board"; + compatible = "st,stm32mp157c-dk2-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; diff --git a/core/arch/arm/dts/stm32mp157c-dk2.dts b/core/arch/arm/dts/stm32mp157c-dk2.dts index b82730cbcbec4a1403009afed411504bda5548f5..dfb8f9830fd61235084ec7e285792d0788eaac80 100644 --- a/core/arch/arm/dts/stm32mp157c-dk2.dts +++ b/core/arch/arm/dts/stm32mp157c-dk2.dts @@ -98,10 +98,6 @@ }; }; -&rcc { - status = "okay"; -}; - &usart2 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&usart2_pins_c>; diff --git a/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts new file mode 100644 index 0000000000000000000000000000000000000000..19cf9bc6b9368a5ec5c3c1f1fd4da979639e367c --- /dev/null +++ b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ +/dts-v1/; + +#include "stm32mp157c-ed1.dts" + +/ { + model = "STMicroelectronics STM32MP157C SCMI eval daughter"; + compatible = "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; +}; + +&iwdg1 { + timeout-sec = <32>; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; diff --git a/core/arch/arm/dts/stm32mp157c-ed1.dts b/core/arch/arm/dts/stm32mp157c-ed1.dts index 1c5ab2d49868bb4999478b19ac11897830f09667..c0b4e1a294d69e8b8b1da94de7cdb51d666c4742 100644 --- a/core/arch/arm/dts/stm32mp157c-ed1.dts +++ b/core/arch/arm/dts/stm32mp157c-ed1.dts @@ -54,6 +54,12 @@ no-map; }; + ipc_shmem: ipc-shmem@1004f000 { + compatible = "shared-dma-pool"; + reg = <0x10048000 0x8000>; + no-map; + }; + mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; @@ -253,6 +259,7 @@ vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = <IT_CURLIM_LDO4 0>; + regulator-always-on; }; vdd_sd: ldo5 { @@ -313,17 +320,17 @@ &iwdg1 { timeout-sec = <32>; + status = "okay"; }; &iwdg2 { timeout-sec = <32>; - status = "okay"; - secure-status = "disabled"; + status = "disabled"; }; &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, - <&vdev0vring1>, <&vdev0buffer>; + <&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; mbox-names = "vq0", "vq1", "shutdown", "detach"; interrupt-parent = <&exti>; @@ -337,6 +344,7 @@ }; &rcc { + compatible = "st,stm32mp1-rcc"; status = "okay"; }; diff --git a/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts b/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts new file mode 100644 index 0000000000000000000000000000000000000000..5474c9af46bc61068fe8d3ab5db0b1937c8365fb --- /dev/null +++ b/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ +/dts-v1/; + +#include "stm32mp157c-ev1.dts" + +/ { + model = "STMicroelectronics STM32MP157C SCMI eval daughter on eval mother"; + compatible = "st,stm32mp157c-ev1-scmi", "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; diff --git a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi index cb4b6ac7d49244eaabbd10dc13d84c031ea3aa61..af5a0534455a43ba0f30232150ff6a2d5f55a497 100644 --- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi @@ -42,6 +42,12 @@ no-map; }; + ipc_shmem: ipc-shmem@1004f000 { + compatible = "shared-dma-pool"; + reg = <0x10048000 0x8000>; + no-map; + }; + mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; @@ -360,6 +366,7 @@ vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = <IT_CURLIM_LDO4 0>; + regulator-always-on; }; vdda: ldo5 { @@ -451,12 +458,12 @@ &iwdg1 { timeout-sec = <32>; + status = "okay"; }; &iwdg2 { timeout-sec = <32>; - status = "okay"; - secure-status = "disabled"; + status = "disabled"; }; <dc { @@ -475,7 +482,7 @@ &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, - <&vdev0vring1>, <&vdev0buffer>; + <&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; mbox-names = "vq0", "vq1", "shutdown", "detach"; interrupt-parent = <&exti>; @@ -488,6 +495,11 @@ vdd_3v3_usbfs-supply = <&vdd_usb>; }; +&rcc { + compatible = "st,stm32mp1-rcc"; + status = "okay"; +}; + &rng1 { status = "okay"; }; diff --git a/core/arch/arm/dts/stm32mp25-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5bd27767fbf5974dcbd14dd25e0aa8e167b975eb --- /dev/null +++ b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ +#include <dt-bindings/pinctrl/stm32-pinfunc.h> + diff --git a/core/arch/arm/dts/stm32mp251.dtsi b/core/arch/arm/dts/stm32mp251.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..edbf84679c5a646d97cd2328e6c3fe28b87d449c --- /dev/null +++ b/core/arch/arm/dts/stm32mp251.dtsi @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + intc: interrupt-controller@4ac00000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x4ac10000 0x0 0x1000>, + <0x0 0x4ac20000 0x0 0x2000>, + <0x0 0x4ac40000 0x0 0x2000>, + <0x0 0x4ac60000 0x0 0x2000>; + #address-cells = <1>; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_msi: clk-msi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + + clk_i2sin: clk-i2sin { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + clocks { + clk_rcbsec: clk-rcbsec { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + }; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges = <0x0 0x0 0x0 0x80000000>; + + rifsc: rifsc@42080000 { + reg = <0x42080000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + usart2: serial@400e0000 { + reg = <0x400e0000 0x400>; + status = "disabled"; + }; + }; + + pinctrl: pinctrl@44240000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-pinctrl"; + ranges = <0 0x44240000 0xa0400>; + pins-are-numbered; + + gpioa: gpio@44240000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@44250000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x10000 0x400>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@44260000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x20000 0x400>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@44270000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x30000 0x400>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@44280000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40000 0x400>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@44290000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x50000 0x400>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@442a0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x60000 0x400>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@442b0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x70000 0x400>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@442c0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x80000 0x400>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@442d0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x90000 0x400>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@442e0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa0000 0x400>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pinctrl-z@46200000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-z-pinctrl"; + ranges = <0 0x46200000 0x400>; + pins-are-numbered; + + gpioz: gpio@46200000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; + }; +}; diff --git a/core/arch/arm/dts/stm32mp253.dtsi b/core/arch/arm/dts/stm32mp253.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..93b7ab8dbc8fecb4193610216610659d33c90835 --- /dev/null +++ b/core/arch/arm/dts/stm32mp253.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ +#include "stm32mp251.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + }; + }; +}; diff --git a/core/arch/arm/dts/stm32mp255.dtsi b/core/arch/arm/dts/stm32mp255.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..e6fa596211f5c0aa5f5b8e338fd354e5ae0ee213 --- /dev/null +++ b/core/arch/arm/dts/stm32mp255.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ +#include "stm32mp253.dtsi" + +/ { +}; diff --git a/core/arch/arm/dts/stm32mp257.dtsi b/core/arch/arm/dts/stm32mp257.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5c5000d3d9dbc2064c3f3aad3a349403a64027f4 --- /dev/null +++ b/core/arch/arm/dts/stm32mp257.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ +#include "stm32mp255.dtsi" + +/ { +}; diff --git a/core/arch/arm/dts/stm32mp257f-ev1.dts b/core/arch/arm/dts/stm32mp257f-ev1.dts new file mode 100644 index 0000000000000000000000000000000000000000..3219c1e12f8d1495442ce7c220b917064699d854 --- /dev/null +++ b/core/arch/arm/dts/stm32mp257f-ev1.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp25-pinctrl.dtsi" +#include "stm32mp257.dtsi" +#include "stm32mp25xf.dtsi" +#include "stm32mp25xxai-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP257F-EV1 Evaluation Board"; + compatible = "st,stm32mp257f-ev1", "st,stm32mp257"; + + aliases { + serial0 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x1 0x00000000>; + }; +}; diff --git a/core/arch/arm/dts/stm32mp25xc.dtsi b/core/arch/arm/dts/stm32mp25xc.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a --- /dev/null +++ b/core/arch/arm/dts/stm32mp25xc.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +/ { +}; diff --git a/core/arch/arm/dts/stm32mp25xf.dtsi b/core/arch/arm/dts/stm32mp25xf.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a --- /dev/null +++ b/core/arch/arm/dts/stm32mp25xf.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +/ { +}; diff --git a/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4fb8920114e8e6069b2fa9f14fc3ee86a68b08b0 --- /dev/null +++ b/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@442d0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@442e0000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..b758b2ceee21e0b13356af737535e30b6cf0744f --- /dev/null +++ b/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..b758b2ceee21e0b13356af737535e30b6cf0744f --- /dev/null +++ b/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/core/arch/arm/include/arm.h b/core/arch/arm/include/arm.h index 0eea4385665c13b6373723f5b9df4da3d8c7ce35..43504ba5b05ab501b0c8817c676497c8b8786f4d 100644 --- a/core/arch/arm/include/arm.h +++ b/core/arch/arm/include/arm.h @@ -3,8 +3,8 @@ * Copyright (c) 2015, Linaro Limited * Copyright (c) 2019-2023, Arm Limited. All rights reserved. */ -#ifndef ARM_H -#define ARM_H +#ifndef __ARM_H +#define __ARM_H #include <stdbool.h> #include <stdint.h> @@ -200,4 +200,4 @@ static inline bool feat_pauth_is_implemented(void) #endif -#endif /*ARM_H*/ +#endif /*__ARM_H*/ diff --git a/core/arch/arm/include/arm32.h b/core/arch/arm/include/arm32.h index 253b197ff1fa410deaf99d8c6bf50acc0310be60..ef729d492dbced44ac4e19d71552fdbc3394285b 100644 --- a/core/arch/arm/include/arm32.h +++ b/core/arch/arm/include/arm32.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef ARM32_H -#define ARM32_H +#ifndef __ARM32_H +#define __ARM32_H #include <compiler.h> #include <sys/cdefs.h> @@ -278,4 +278,4 @@ static __always_inline __noprof uint32_t read_r7(void) #endif /*__ASSEMBLER__*/ -#endif /*ARM32_H*/ +#endif /*__ARM32_H*/ diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h index 8c210b3fa4ee42f407389d9f81f6c62db5ed9073..23a21c41c42e6b86a941b2b05515dadf9b09f4f8 100644 --- a/core/arch/arm/include/arm64.h +++ b/core/arch/arm/include/arm64.h @@ -3,8 +3,8 @@ * Copyright (c) 2015, Linaro Limited * Copyright (c) 2023, Arm Limited */ -#ifndef ARM64_H -#define ARM64_H +#ifndef __ARM64_H +#define __ARM64_H #include <compiler.h> #include <sys/cdefs.h> @@ -240,6 +240,8 @@ #define FEAT_MTE2_IMPLEMENTED U(0x2) #define FEAT_MTE3_IMPLEMENTED U(0x3) +#define ID_AA64MMFR0_EL1_PARANGE_MASK UL(0xf) + #define ID_AA64MMFR1_EL1_PAN_MASK UL(0xf) #define ID_AA64MMFR1_EL1_PAN_SHIFT U(20) #define FEAT_PAN_NOT_IMPLEMENTED U(0x0) @@ -371,6 +373,19 @@ static inline void write_64bit_pair(uint64_t dst, uint64_t hi, uint64_t lo) "r" (hi), "r" (lo), "r" (dst) : "memory"); } +static inline void read_64bit_pair(uint64_t src, uint64_t *hi, uint64_t *lo) +{ + uint64_t tmp0 = 0; + uint64_t tmp1 = 0; + + /* 128bits should be read from hardware at one time */ + asm volatile ("ldp %0, %1, [%2]\n" : "=&r"(tmp0), "=&r"(tmp1) : + "r"(src) : "memory"); + + *lo = tmp0; + *hi = tmp1; +} + /* * Templates for register read/write functions based on mrs/msr */ @@ -455,6 +470,7 @@ DEFINE_U64_REG_READ_FUNC(par_el1) DEFINE_U64_REG_WRITE_FUNC(mair_el1) +DEFINE_U64_REG_READ_FUNC(id_aa64mmfr0_el1) DEFINE_U64_REG_READ_FUNC(id_aa64mmfr1_el1) DEFINE_U64_REG_READ_FUNC(id_aa64pfr1_el1) DEFINE_U64_REG_READ_FUNC(id_aa64isar0_el1) @@ -504,5 +520,5 @@ static inline void write_pan_disable(void) #endif /*__ASSEMBLER__*/ -#endif /*ARM64_H*/ +#endif /*__ARM64_H*/ diff --git a/core/arch/arm/include/crypto/ghash-ce-core.h b/core/arch/arm/include/crypto/ghash-ce-core.h index b0f9f5457f988492c5726e89849087dbb973280f..e2be237f8baa81a00929387e0792334d956b1e31 100644 --- a/core/arch/arm/include/crypto/ghash-ce-core.h +++ b/core/arch/arm/include/crypto/ghash-ce-core.h @@ -3,8 +3,8 @@ * Copyright (c) 2017-2020, Linaro Limited */ -#ifndef __GHASH_CE_CORE_H -#define __GHASH_CE_CORE_H +#ifndef __CRYPTO_GHASH_CE_CORE_H +#define __CRYPTO_GHASH_CE_CORE_H #include <inttypes.h> @@ -40,4 +40,4 @@ uint32_t pmull_gcm_aes_sub(uint32_t input); void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds); -#endif /*__GHASH_CE_CORE_H*/ +#endif /*__CRYPTO_GHASH_CE_CORE_H*/ diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h index c54479b663eec27721fcf64c5590f8d9febedfe4..1a7baccfb1f21c4dcacdb73a3f14a196f2498c0f 100644 --- a/core/arch/arm/include/ffa.h +++ b/core/arch/arm/include/ffa.h @@ -92,6 +92,9 @@ #define FFA_CONSOLE_LOG_32 U(0x8400008A) #define FFA_CONSOLE_LOG_64 U(0xC400008A) +#define FFA_FEATURES_FUNC_ID_MASK BIT32(31) +#define FFA_FEATURES_FEATURE_ID_MASK GENMASK_32(7, 0) + #define FFA_FEATURE_NOTIF_PEND_INTR U(0x1) #define FFA_FEATURE_SCHEDULE_RECV_INTR U(0x2) #define FFA_FEATURE_MANAGED_EXIT_INTR U(0x3) diff --git a/core/arch/arm/include/kernel/misc_arch.h b/core/arch/arm/include/kernel/misc_arch.h index 0653119d569171e967ef60444f0467f8c3a0b157..992c75f7c8cf107a302bd02e3e0f23a81f916975 100644 --- a/core/arch/arm/include/kernel/misc_arch.h +++ b/core/arch/arm/include/kernel/misc_arch.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef KERNEL_MISC_ARCH_H -#define KERNEL_MISC_ARCH_H +#ifndef __KERNEL_MISC_ARCH_H +#define __KERNEL_MISC_ARCH_H #include <arm.h> #include <kernel/thread.h> @@ -17,4 +17,4 @@ uint32_t read_mode_lr(int cpu_mode); void wait_cycles(unsigned long cycles); -#endif /*KERNEL_MISC_ARCH_H*/ +#endif /*__KERNEL_MISC_ARCH_H*/ diff --git a/core/arch/arm/include/kernel/tee_l2cc_mutex.h b/core/arch/arm/include/kernel/tee_l2cc_mutex.h index 1011fced92ff0c58bde220b6a94a46df3d147d3d..7fb5af3e2872aa39fb438560e8c7c36b3b1a227f 100644 --- a/core/arch/arm/include/kernel/tee_l2cc_mutex.h +++ b/core/arch/arm/include/kernel/tee_l2cc_mutex.h @@ -2,8 +2,9 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_L2CC_MUTEX_H -#define TEE_L2CC_MUTEX_H +#ifndef __KERNEL_TEE_L2CC_MUTEX_H +#define __KERNEL_TEE_L2CC_MUTEX_H + #include <inttypes.h> #include <tee_api_types.h> #include <tee_api_defines.h> @@ -47,4 +48,4 @@ static inline TEE_Result tee_set_l2cc_mutex(paddr_t *mutex __unused) } #endif -#endif /* TEE_L2CC_MUTEX_H */ +#endif /* __KERNEL_TEE_L2CC_MUTEX_H */ diff --git a/core/arch/arm/include/kernel/thread_spmc.h b/core/arch/arm/include/kernel/thread_spmc.h index ffef0903633f2f8bd8dcf0ba262749c14ee58eb2..672bc2cc82ebfb5c80f18d223fbf6cbdab6cc7e9 100644 --- a/core/arch/arm/include/kernel/thread_spmc.h +++ b/core/arch/arm/include/kernel/thread_spmc.h @@ -1,11 +1,14 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Arm Limited. + * Copyright (c) 2023, Linaro Limited */ #ifndef __KERNEL_THREAD_SPMC_H #define __KERNEL_THREAD_SPMC_H +#include <compiler.h> #include <ffa.h> +#include <kernel/panic.h> #include <kernel/thread.h> /* FF-A endpoint base ID when OP-TEE is used as a S-EL1 endpoint */ @@ -37,7 +40,14 @@ TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen, struct ffa_mem_transaction_x *trans); -#if !defined(CFG_CORE_SEL1_SPMC) +#if defined(CFG_CORE_SEL1_SPMC) +void thread_spmc_set_async_notif_intid(int intid); +#else +static inline void __noreturn +thread_spmc_set_async_notif_intid(int intid __unused) +{ + panic(); +} struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie); void thread_spmc_relinquish(uint64_t memory_region_handle); #endif diff --git a/core/arch/arm/include/kernel/tlb_helpers.h b/core/arch/arm/include/kernel/tlb_helpers.h index 36a9af396cd2c89ded256a55cad0a9dd8a214f88..92d596aeedacf3ed9d3ed8379c5867aacb09a4cb 100644 --- a/core/arch/arm/include/kernel/tlb_helpers.h +++ b/core/arch/arm/include/kernel/tlb_helpers.h @@ -4,8 +4,8 @@ * Copyright (c) 2017, Linaro Limited */ -#ifndef TLB_HELPERS_H -#define TLB_HELPERS_H +#ifndef __KERNEL_TLB_HELPERS_H +#define __KERNEL_TLB_HELPERS_H #include <arm.h> @@ -48,4 +48,4 @@ static inline void tlbi_va_asid(vaddr_t va, uint32_t asid) } #endif /*!__ASSEMBLER__*/ -#endif /* TLB_HELPERS_H */ +#endif /* __KERNEL_TLB_HELPERS_H */ diff --git a/core/arch/arm/include/kernel/tz_proc_def.h b/core/arch/arm/include/kernel/tz_proc_def.h index 6e9097dfe072f561d8ec087624d59d4674003a6e..2d69b853e00f9492ac2852ee7e25de873254ccb0 100644 --- a/core/arch/arm/include/kernel/tz_proc_def.h +++ b/core/arch/arm/include/kernel/tz_proc_def.h @@ -3,6 +3,9 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ +#ifndef __KERNEL_TZ_PROC_DEF_H +#define __KERNEL_TZ_PROC_DEF_H + #include <stdint.h> /* @@ -89,3 +92,5 @@ #define LINE_FIELD_OVERFLOW U(13) /* start of way number field offset in way/index format */ #define WAY_FIELD_OFFSET U(30) + +#endif /*__KERNEL_TZ_PROC_DEF_H*/ diff --git a/core/arch/arm/include/kernel/tz_ssvce_def.h b/core/arch/arm/include/kernel/tz_ssvce_def.h index 25215b537f7cd3a12f2ca465a7c06d540ca2fb9d..e69e81b7a9017d291d2adde2994557bbb0c884cc 100644 --- a/core/arch/arm/include/kernel/tz_ssvce_def.h +++ b/core/arch/arm/include/kernel/tz_ssvce_def.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TZ_SSVCE_DEF_H -#define TZ_SSVCE_DEF_H +#ifndef __KERNEL_TZ_SSVCE_DEF_H +#define __KERNEL_TZ_SSVCE_DEF_H #include <stdint.h> #include <util.h> @@ -125,4 +125,4 @@ */ #define CORE_ICC_ICCPMR U(0x0004) -#endif /* TZ_SSVCE_DEF_H */ +#endif /* __KERNEL_TZ_SSVCE_DEF_H */ diff --git a/core/arch/arm/include/kernel/tz_ssvce_pl310.h b/core/arch/arm/include/kernel/tz_ssvce_pl310.h index 2bcd26ebe757f31467349301ce6255ab7b89107b..7112c095eed7f063760242847bf9cb2639fdba24 100644 --- a/core/arch/arm/include/kernel/tz_ssvce_pl310.h +++ b/core/arch/arm/include/kernel/tz_ssvce_pl310.h @@ -3,14 +3,16 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TZ_SSVCE_PL310_H -#define TZ_SSVCE_PL310_H +#ifndef __KERNEL_TZ_SSVCE_PL310_H +#define __KERNEL_TZ_SSVCE_PL310_H #include <util.h> #include <kernel/tz_ssvce_def.h> #include <types_ext.h> vaddr_t pl310_base(void); +vaddr_t pl310_nsbase(void); + /* * End address is included in the range (last address in range) */ @@ -21,4 +23,4 @@ void arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); -#endif /* TZ_SSVCE_PL310_H */ +#endif /* __KERNEL_TZ_SSVCE_PL310_H */ diff --git a/core/arch/arm/include/kernel/vfp.h b/core/arch/arm/include/kernel/vfp.h index 49c0d736ce7506db989bccb8d5a6fca50271008d..f42ca9795f7e08ecd6f9a512d488c40b63140116 100644 --- a/core/arch/arm/include/kernel/vfp.h +++ b/core/arch/arm/include/kernel/vfp.h @@ -3,8 +3,8 @@ * Copyright (c) 2015, Linaro Limited */ -#ifndef KERNEL_VFP_H -#define KERNEL_VFP_H +#ifndef __KERNEL_VFP_H +#define __KERNEL_VFP_H #include <types_ext.h> #include <compiler.h> @@ -103,4 +103,4 @@ void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save); */ void vfp_lazy_restore_state(struct vfp_state *state, bool full_state); -#endif /*KERNEL_VFP_H*/ +#endif /*__KERNEL_VFP_H*/ diff --git a/core/arch/arm/include/mm/core_mmu_arch.h b/core/arch/arm/include/mm/core_mmu_arch.h index 42f382fd5c26090e99c3d6f1ef06477b771f60f8..d8154d7efdff7e44ca5a6e50748c6c875882e90f 100644 --- a/core/arch/arm/include/mm/core_mmu_arch.h +++ b/core/arch/arm/include/mm/core_mmu_arch.h @@ -3,8 +3,8 @@ * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef __CORE_MMU_ARCH_H -#define __CORE_MMU_ARCH_H +#ifndef __MM_CORE_MMU_ARCH_H +#define __MM_CORE_MMU_ARCH_H #ifndef __ASSEMBLER__ #include <arm.h> @@ -175,10 +175,14 @@ static inline TEE_Result cache_op_outer(enum cache_op op __unused, /* Do section mapping, not support on LPAE */ void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb); +#if defined(ARM64) +unsigned int core_mmu_arm64_get_pa_width(void); +#endif + static inline bool core_mmu_check_max_pa(paddr_t pa __maybe_unused) { #if defined(ARM64) - return pa <= (BIT64(CFG_CORE_ARM64_PA_BITS) - 1); + return pa <= (BIT64(core_mmu_arm64_get_pa_width()) - 1); #elif defined(CFG_CORE_LARGE_PHYS_ADDR) return pa <= (BIT64(40) - 1); #else @@ -223,4 +227,4 @@ static inline bool core_mmu_level_in_range(unsigned int level) #endif /*__ASSEMBLER__*/ -#endif /* CORE_MMU_H */ +#endif /* __MM_CORE_MMU_ARCH_H */ diff --git a/core/arch/arm/include/mm/generic_ram_layout.h b/core/arch/arm/include/mm/generic_ram_layout.h index b3e0ac393b3dda2da0ec6f6fa3ce73318d501c8e..367dd35760d16e9edefd72fcd8836f76ac159b5f 100644 --- a/core/arch/arm/include/mm/generic_ram_layout.h +++ b/core/arch/arm/include/mm/generic_ram_layout.h @@ -133,7 +133,7 @@ #endif #endif -#if defined(CFG_TZSRAM_START) +#if defined(CFG_WITH_PAGER) && defined(CFG_TZSRAM_START) #define TZSRAM_BASE CFG_TZSRAM_START #define TZSRAM_SIZE CFG_TZSRAM_SIZE #endif diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h index 8f1603946bf4a8590c1da37d2e7a5e42b23faad2..8db02650be578b26141d302bd2338b853020851d 100644 --- a/core/arch/arm/include/optee_ffa.h +++ b/core/arch/arm/include/optee_ffa.h @@ -74,7 +74,7 @@ * * Call register usage: * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES - * w4-w7: Note used (MBZ) + * w4-w7: Not used (MBZ) * * Return register usage: * w3: Error code, 0 on success @@ -82,15 +82,17 @@ * as the second MSG arg struct for * OPTEE_FFA_YIELDING_CALL_WITH_ARG. * Bit[31:8]: Reserved (MBZ) - * w5: Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below, - * unused bits MBZ. - * w6-w7: Not used (MBZ) + * w5: Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_* + * w6: The maximum secure world notification number + * w7: Not used (MBZ) */ /* * Secure world supports using an offset into the argument shared memory * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG */ #define OPTEE_FFA_SEC_CAP_ARG_OFFSET BIT(0) +/* OP-TEE supports asynchronous notification via FF-A */ +#define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF BIT(1) #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) @@ -109,6 +111,21 @@ */ #define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) +/* + * Inform OP-TEE that normal world is able to receive asynchronous + * notifications. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF + * w4: Notification value to request bottom half processing + * w5-w7: Not used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4-w7: Not used (MBZ) + */ +#define OPTEE_FFA_ENABLE_ASYNC_NOTIF OPTEE_FFA_BLOCKING_CALL(5) + /* * Call with struct optee_msg_arg as argument in the supplied shared memory * with a zero internal offset and normal cached memory attributes. diff --git a/core/arch/arm/include/scmi/scmi_server.h b/core/arch/arm/include/scmi/scmi_server.h index a28fd667f11daec57fdc46fee1c3a4e40d2acda3..d969e238d118660ca5a54886979ad42d91af7a99 100644 --- a/core/arch/arm/include/scmi/scmi_server.h +++ b/core/arch/arm/include/scmi/scmi_server.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2019-2022, Linaro Limited */ -#ifndef SCMI_SERVER_H -#define SCMI_SERVER_H +#ifndef __SCMI_SCMI_SERVER_H +#define __SCMI_SCMI_SERVER_H #include <tee_api_types.h> #include <types_ext.h> @@ -70,4 +70,4 @@ static inline int scmi_server_get_channels_count(void) return 0; } #endif /* CFG_SCMI_SCPFW */ -#endif /* SCMI_SERVER_H */ +#endif /* __SCMI_SCMI_SERVER_H */ diff --git a/core/arch/arm/include/sm/optee_smc.h b/core/arch/arm/include/sm/optee_smc.h index 04a3839a2c183d4abd18b5da525208fd9bc5fd65..fe9aff0e1fc29135c7dda790d6372bcba324b7b8 100644 --- a/core/arch/arm/include/sm/optee_smc.h +++ b/core/arch/arm/include/sm/optee_smc.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015-2021, Linaro Limited */ -#ifndef OPTEE_SMC_H -#define OPTEE_SMC_H +#ifndef __SM_OPTEE_SMC_H +#define __SM_OPTEE_SMC_H #include <stdint.h> @@ -705,4 +705,4 @@ ((((ret) & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \ OPTEE_SMC_RETURN_RPC_PREFIX))) -#endif /* OPTEE_SMC_H */ +#endif /* __SM_OPTEE_SMC_H */ diff --git a/core/arch/arm/include/sm/pm.h b/core/arch/arm/include/sm/pm.h index 939f966e896b2765eb32bf1beac0932739bbfd96..351095a9bffc66d75fbc764a08a6eb52c455a9f7 100644 --- a/core/arch/arm/include/sm/pm.h +++ b/core/arch/arm/include/sm/pm.h @@ -26,8 +26,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SM_PM_H -#define SM_PM_H +#ifndef __SM_PM_H +#define __SM_PM_H #include <stdint.h> #include <types_ext.h> diff --git a/core/arch/arm/include/sm/psci.h b/core/arch/arm/include/sm/psci.h index b992e60ae62607764c078a10f71d7de0e33b4033..95ccdfa4c2149c67bf81d28066974c58978933d3 100644 --- a/core/arch/arm/include/sm/psci.h +++ b/core/arch/arm/include/sm/psci.h @@ -1,3 +1,10 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2023, Linaro Limited + */ +#ifndef __SM_PSCI_H +#define __SM_PSCI_H + #include <kernel/thread.h> #include <sm/sm.h> #include <stdint.h> @@ -79,3 +86,4 @@ int psci_stat_count(uint32_t cpu_id, uint32_t power_state); void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec); void psci_armv7_cpu_off(void); +#endif /* __SM_PSCI_H */ diff --git a/core/arch/arm/include/sm/sm.h b/core/arch/arm/include/sm/sm.h index d33c5fc5ce29fb40664b8887a43ee5e430af9b82..9e7b9879149c3a15117257d4f2176390dffd60cc 100644 --- a/core/arch/arm/include/sm/sm.h +++ b/core/arch/arm/include/sm/sm.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef SM_SM_H -#define SM_SM_H +#ifndef __SM_SM_H +#define __SM_SM_H #ifndef __ASSEMBLER__ @@ -142,4 +142,4 @@ void vector_fiq_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, #define SM_EXIT_TO_NON_SECURE 0 #define SM_EXIT_TO_SECURE 1 -#endif /*SM_SM_H*/ +#endif /*__SM_SM_H*/ diff --git a/core/arch/arm/include/sm/std_smc.h b/core/arch/arm/include/sm/std_smc.h index ce8606dcfdd711747c9b8de31c3e5bb57e4810e7..80e71a83107ea091c4dbed94b3656b813a2738c3 100644 --- a/core/arch/arm/include/sm/std_smc.h +++ b/core/arch/arm/include/sm/std_smc.h @@ -1,5 +1,9 @@ -#ifndef __STD_SMC_H__ -#define __STD_SMC_H__ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2023, Linaro Limited + */ +#ifndef __SM_STD_SMC_H__ +#define __SM_STD_SMC_H__ #include <sm/sm.h> diff --git a/core/arch/arm/include/sm/teesmc_opteed.h b/core/arch/arm/include/sm/teesmc_opteed.h index 41e7204d7fabf7f562177397dc8c1cfbf3e07d43..7213531aae270d6040a33f20d2229ae797ce5b17 100644 --- a/core/arch/arm/include/sm/teesmc_opteed.h +++ b/core/arch/arm/include/sm/teesmc_opteed.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEESMC_OPTEED_H -#define TEESMC_OPTEED_H +#ifndef __SM_TEESMC_OPTEED_H +#define __SM_TEESMC_OPTEED_H /* * This file specify SMC function IDs used when returning from TEE to the @@ -117,4 +117,4 @@ #define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) -#endif /*TEESMC_OPTEED_H*/ +#endif /*__SM_TEESMC_OPTEED_H*/ diff --git a/core/arch/arm/include/sm/teesmc_opteed_macros.h b/core/arch/arm/include/sm/teesmc_opteed_macros.h index fcc84b72f5bb8da35008c060e2b3c2b9bb4350b3..2171c62839a46edc960dcf1132812af5228dc367 100644 --- a/core/arch/arm/include/sm/teesmc_opteed_macros.h +++ b/core/arch/arm/include/sm/teesmc_opteed_macros.h @@ -3,11 +3,11 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEESMC_OPTEED_MACROS_H -#define TEESMC_OPTEED_MACROS_H +#ifndef __SM_TEESMC_OPTEED_MACROS_H +#define __SM_TEESMC_OPTEED_MACROS_H #define TEESMC_OPTEED_RV(func_num) \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED, (func_num)) -#endif /*TEESMC_OPTEED_MACROS_H*/ +#endif /*__SM_TEESMC_OPTEED_MACROS_H*/ diff --git a/core/arch/arm/include/sm/watchdog_smc.h b/core/arch/arm/include/sm/watchdog_smc.h index b8b55a489334f716f01e991fdaf0ba0522bee13c..555d519f79093f214cfa33009bd7ef9ada509241 100644 --- a/core/arch/arm/include/sm/watchdog_smc.h +++ b/core/arch/arm/include/sm/watchdog_smc.h @@ -2,8 +2,8 @@ /* * Copyright (C) STMicroelectronics 2023 */ -#ifndef SM_WATCHDOG_SMC_H -#define SM_WATCHDOG_SMC_H +#ifndef __SM_WATCHDOG_SMC_H +#define __SM_WATCHDOG_SMC_H /* * This file describes the secure watchdog management service. @@ -78,4 +78,4 @@ * a7 Hypervisor Client ID register */ -#endif /* SM_WATCHDOG_SMC_H */ +#endif /* __SM_WATCHDOG_SMC_H */ diff --git a/core/arch/arm/include/tee/entry_fast.h b/core/arch/arm/include/tee/entry_fast.h index 0f6fef8cc75f866acfcaa8d8cd6488919963b0d9..b6e77dabfaae0ba721722cd82140ec5c93429111 100644 --- a/core/arch/arm/include/tee/entry_fast.h +++ b/core/arch/arm/include/tee/entry_fast.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_ENTRY_FAST_H -#define TEE_ENTRY_FAST_H +#ifndef __TEE_ENTRY_FAST_H +#define __TEE_ENTRY_FAST_H #include <kernel/thread.h> @@ -30,4 +30,4 @@ size_t tee_entry_generic_get_api_call_count(void); void tee_entry_fast(struct thread_smc_args *args); void __tee_entry_fast(struct thread_smc_args *args); -#endif /* TEE_ENTRY_FAST_H */ +#endif /* __TEE_ENTRY_FAST_H */ diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c index 9a132240eb213a9244060a04b62216101385eaa7..275eb8cfb242b0a69bf8d5172abe5e30144ce232 100644 --- a/core/arch/arm/kernel/boot.c +++ b/core/arch/arm/kernel/boot.c @@ -15,6 +15,7 @@ #include <ffa.h> #include <initcall.h> #include <inttypes.h> +#include <io.h> #include <keep.h> #include <kernel/asan.h> #include <kernel/boot.h> @@ -25,6 +26,7 @@ #include <kernel/tee_misc.h> #include <kernel/thread.h> #include <kernel/tpm.h> +#include <kernel/transfer_list.h> #include <libfdt.h> #include <malloc.h> #include <memtag.h> @@ -78,9 +80,12 @@ uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; DECLARE_KEEP_PAGER(sem_cpu_sync); #endif -#ifdef CFG_CORE_FFA static void *manifest_dt __nex_bss; -#endif +static unsigned long boot_arg_fdt __nex_bss; +static unsigned long boot_arg_nsec_entry __nex_bss; +static unsigned long boot_arg_pageable_part __nex_bss; +static unsigned long boot_arg_transfer_list __nex_bss; +static struct transfer_list_header *mapped_tl __nex_bss; #ifdef CFG_SECONDARY_INIT_CNTFRQ static uint32_t cntfrq; @@ -673,7 +678,8 @@ static int add_optee_dt_node(struct dt_descriptor *dt) uint32_t val[3] = { }; /* PPI are visible only in current CPU cluster */ - static_assert(!CFG_CORE_ASYNC_NOTIF_GIC_INTID || + static_assert(IS_ENABLED(CFG_CORE_FFA) || + !CFG_CORE_ASYNC_NOTIF_GIC_INTID || (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_SPI_BASE) || ((CFG_TEE_CORE_NB_CORE <= 8) && @@ -973,8 +979,9 @@ void *get_manifest_dt(void) return manifest_dt; } -static void init_manifest_dt(unsigned long pa) +static void reinit_manifest_dt(void) { + paddr_t pa = (unsigned long)manifest_dt; void *fdt = NULL; int ret = 0; @@ -1018,7 +1025,7 @@ void *get_manifest_dt(void) return NULL; } -static void init_manifest_dt(unsigned long pa __unused) +static void reinit_manifest_dt(void) { } #endif /*CFG_CORE_FFA*/ @@ -1170,17 +1177,21 @@ static bool cpu_nmfi_enabled(void) * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ -void __weak boot_init_primary_late(unsigned long fdt, - unsigned long manifest) +void __weak boot_init_primary_late(unsigned long fdt __unused, + unsigned long manifest __unused) { - init_external_dt(fdt); - /* - * With an SPMC at S-EL2 we have saved the physical fdt address - * from the passed boot info. - */ - if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) - manifest = (unsigned long)get_manifest_dt(); - init_manifest_dt(manifest); + size_t fdt_size = CFG_DTB_MAX_SIZE; + + if (IS_ENABLED(CFG_TRANSFER_LIST) && mapped_tl) { + struct transfer_list_entry *tl_e = NULL; + + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + if (tl_e) + fdt_size = tl_e->data_size; + } + + init_external_dt(boot_arg_fdt, fdt_size); + reinit_manifest_dt(); #ifdef CFG_CORE_SEL1_SPMC tpm_map_log_area(get_manifest_dt()); #else @@ -1191,7 +1202,7 @@ void __weak boot_init_primary_late(unsigned long fdt, configure_console_from_dt(); IMSG("OP-TEE version: %s", core_v_str); - if (IS_ENABLED(CFG_WARN_INSECURE)) { + if (IS_ENABLED(CFG_INSECURE)) { IMSG("WARNING: This OP-TEE configuration might be insecure!"); IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); } @@ -1252,18 +1263,78 @@ static void init_secondary_helper(unsigned long nsec_entry) * Note: this function is weak just to make it possible to exclude it from * the unpaged area so that it lies in the init area. */ -void __weak boot_init_primary_early(unsigned long pageable_part, - unsigned long nsec_entry __maybe_unused) +void __weak boot_init_primary_early(void) { + unsigned long pageable_part = 0; unsigned long e = PADDR_INVALID; + struct transfer_list_entry *tl_e = NULL; -#if !defined(CFG_WITH_ARM_TRUSTED_FW) - e = nsec_entry; -#endif + if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) + e = boot_arg_nsec_entry; + + if (IS_ENABLED(CFG_TRANSFER_LIST) && boot_arg_transfer_list) { + /* map and save the TL */ + mapped_tl = transfer_list_map(boot_arg_transfer_list); + if (!mapped_tl) + panic("Failed to map transfer list"); + + transfer_list_dump(mapped_tl); + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + if (tl_e) { + /* + * Expand the data size of the DTB entry to the maximum + * allocable mapped memory to reserve sufficient space + * for inserting new nodes, avoid potentially corrupting + * next entries. + */ + uint32_t dtb_max_sz = mapped_tl->max_size - + mapped_tl->size + tl_e->data_size; + + if (!transfer_list_set_data_size(mapped_tl, tl_e, + dtb_max_sz)) { + EMSG("Failed to extend DTB size to %#"PRIx32, + dtb_max_sz); + panic(); + } + } + tl_e = transfer_list_find(mapped_tl, TL_TAG_OPTEE_PAGABLE_PART); + } + + if (IS_ENABLED(CFG_WITH_PAGER)) { + if (IS_ENABLED(CFG_TRANSFER_LIST) && tl_e) + pageable_part = + get_le64(transfer_list_entry_data(tl_e)); + else + pageable_part = boot_arg_pageable_part; + } init_primary(pageable_part, e); } +static void boot_save_transfer_list(unsigned long zero_reg, + unsigned long transfer_list, + unsigned long fdt) +{ + struct transfer_list_header *tl = (void *)transfer_list; + struct transfer_list_entry *tl_e = NULL; + + if (zero_reg != 0) + panic("Incorrect transfer list register convention"); + + if (!IS_ALIGNED_WITH_TYPE(transfer_list, struct transfer_list_header) || + !IS_ALIGNED(transfer_list, TL_ALIGNMENT_FROM_ORDER(tl->alignment))) + panic("Transfer list base address is not aligned"); + + if (transfer_list_check_header(tl) == TL_OPS_NONE) + panic("Invalid transfer list"); + + tl_e = transfer_list_find(tl, TL_TAG_FDT); + if (fdt != (unsigned long)transfer_list_entry_data(tl_e)) + panic("DT does not match to the DT entry of the TL"); + + boot_arg_transfer_list = transfer_list; +} + #if defined(CFG_WITH_ARM_TRUSTED_FW) unsigned long boot_cpu_on_handler(unsigned long a0 __maybe_unused, unsigned long a1 __unused) @@ -1321,13 +1392,17 @@ struct ns_entry_context *boot_core_hpen(void) #if defined(CFG_CORE_ASLR) #if defined(CFG_DT) -unsigned long __weak get_aslr_seed(void *fdt) +unsigned long __weak get_aslr_seed(void) { + void *fdt = NULL; int rc = 0; const uint64_t *seed = NULL; int offs = 0; int len = 0; + if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) + fdt = (void *)boot_arg_fdt; + if (!fdt) { DMSG("No fdt"); goto err; @@ -1357,7 +1432,7 @@ err: return plat_get_aslr_seed(); } #else /*!CFG_DT*/ -unsigned long __weak get_aslr_seed(void *fdt __unused) +unsigned long __weak get_aslr_seed(void) { /* Try platform implementation */ return plat_get_aslr_seed(); @@ -1365,7 +1440,6 @@ unsigned long __weak get_aslr_seed(void *fdt __unused) #endif /*!CFG_DT*/ #endif /*CFG_CORE_ASLR*/ -#if defined(CFG_CORE_FFA) static void *get_fdt_from_boot_info(struct ffa_boot_info_header_1_1 *hdr) { struct ffa_boot_info_1_1 *desc = NULL; @@ -1441,16 +1515,136 @@ static void get_sec_mem_from_manifest(void *fdt, paddr_t *base, size_t *size) *size = num; } -void __weak boot_save_boot_info(void *boot_info) +void __weak boot_save_args(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4 __maybe_unused) { - paddr_t base = 0; - size_t size = 0; + /* + * Register use: + * + * Scenario A: Default arguments + * a0 - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n: + * if non-NULL holds the TOS FW config [1] address + * - CFG_CORE_FFA=y && + (CFG_CORE_SEL2_SPMC=y || CFG_CORE_EL3_SPMC=y): + * address of FF-A Boot Information Blob + * - CFG_CORE_FFA=n: + * if non-NULL holds the pagable part address + * a1 - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): + * Armv7 standard bootarg #1 (kept track of in entry_a32.S) + * a2 - CFG_CORE_SEL2_SPMC=n: + * if non-NULL holds the system DTB address + * - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): + * Armv7 standard bootarg #2 (system DTB address, kept track + * of in entry_a32.S) + * a3 - Not used + * a4 - CFG_WITH_ARM_TRUSTED_FW=n: + * Non-secure entry address + * + * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware + * configuration file. Used by Trusted OS (BL32), that is, OP-TEE + * here. This is also called Manifest DT, related to the Manifest DT + * passed in the FF-A Boot Information Blob, but with a different + * compatible string. + + * Scenario B: FW Handoff via Transfer List + * Note: FF-A and non-secure entry are not yet supported with + * Transfer List + * a0 - DTB address or 0 (AArch64) + * - must be 0 (AArch32) + * a1 - TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK + * a2 - must be 0 (AArch64) + * - DTB address or 0 (AArch32) + * a3 - Transfer list base address + * a4 - Not used + */ - manifest_dt = get_fdt_from_boot_info(boot_info); - if (IS_ENABLED(CFG_CORE_SEL2_SPMC) && - IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) { - get_sec_mem_from_manifest(manifest_dt, &base, &size); - core_mmu_set_secure_memory(base, size); + if (IS_ENABLED(CFG_TRANSFER_LIST) && + a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) { + if (IS_ENABLED(CFG_ARM64_core)) { + boot_save_transfer_list(a2, a3, a0); + boot_arg_fdt = a0; + } else { + boot_save_transfer_list(a0, a3, a2); + boot_arg_fdt = a2; + } + return; + } + + if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) { +#if defined(CFG_DT_ADDR) + boot_arg_fdt = CFG_DT_ADDR; +#else + boot_arg_fdt = a2; +#endif + } + + if (IS_ENABLED(CFG_CORE_FFA)) { + if (IS_ENABLED(CFG_CORE_SEL2_SPMC) || + IS_ENABLED(CFG_CORE_EL3_SPMC)) + manifest_dt = get_fdt_from_boot_info((void *)a0); + else + manifest_dt = (void *)a0; + if (IS_ENABLED(CFG_CORE_SEL2_SPMC) && + IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) { + paddr_t base = 0; + size_t size = 0; + + get_sec_mem_from_manifest(manifest_dt, &base, &size); + core_mmu_set_secure_memory(base, size); + } + } else { + if (IS_ENABLED(CFG_WITH_PAGER)) { +#if defined(CFG_PAGEABLE_ADDR) + boot_arg_pageable_part = CFG_PAGEABLE_ADDR; +#else + boot_arg_pageable_part = a0; +#endif + } + if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { +#if defined(CFG_NS_ENTRY_ADDR) + boot_arg_nsec_entry = CFG_NS_ENTRY_ADDR; +#else + boot_arg_nsec_entry = a4; +#endif + } } } -#endif /*CFG_CORE_FFA*/ + +#if defined(CFG_TRANSFER_LIST) +static TEE_Result release_transfer_list(void) +{ + struct dt_descriptor *dt = get_external_dt_desc(); + + if (!mapped_tl) + return TEE_SUCCESS; + + if (dt) { + int ret = 0; + struct transfer_list_entry *tl_e = NULL; + + /* + * Pack the DTB and update the transfer list before un-mapping + */ + ret = fdt_pack(dt->blob); + if (ret < 0) { + EMSG("Failed to pack Device Tree at 0x%" PRIxPA + ": error %d", virt_to_phys(dt->blob), ret); + panic(); + } + + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + assert(dt->blob == transfer_list_entry_data(tl_e)); + transfer_list_set_data_size(mapped_tl, tl_e, + fdt_totalsize(dt->blob)); + dt->blob = NULL; + } + + transfer_list_unmap_sync(mapped_tl); + mapped_tl = NULL; + + return TEE_SUCCESS; +} + +boot_final(release_transfer_list); +#endif diff --git a/core/arch/arm/kernel/entry_a32.S b/core/arch/arm/kernel/entry_a32.S index 2ef44c3d0d8aee3ea212a43c2fe4ffced400c433..a43d36afb7c81030acce22a66e2ea6895832bef1 100644 --- a/core/arch/arm/kernel/entry_a32.S +++ b/core/arch/arm/kernel/entry_a32.S @@ -163,51 +163,6 @@ END_FUNC reset_vect_table write_sctlr r0 .endm -#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_WITH_ARM_TRUSTED_FW) - /* - * With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes - * the DTB in r0, pagable part in r1, and the rest of the registers - * are unused - * - * Save boot arguments passed - * entry r0, saved r6: device tree address - * entry r1, saved r4: pagestore - * saved r5, r7: Zero - */ - .macro bootargs_entry - mov r6, r0 - mov r4, r1 - mov r5, #0 - mov r7, #0 - .endm -#else - /* - * Save boot arguments - * entry r0, saved r4: pagestore - * entry r1, saved r7: (ARMv7 standard bootarg #1) - * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2) - * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0) - */ - .macro bootargs_entry -#if defined(CFG_NS_ENTRY_ADDR) - ldr r5, =CFG_NS_ENTRY_ADDR -#else - mov r5, lr -#endif -#if defined(CFG_PAGEABLE_ADDR) - ldr r4, =CFG_PAGEABLE_ADDR -#else - mov r4, r0 -#endif -#if defined(CFG_DT_ADDR) - ldr r6, =CFG_DT_ADDR -#else - mov r6, r2 -#endif - mov r7, r1 - .endm -#endif - .macro maybe_init_spectre_workaround #if !defined(CFG_WITH_ARM_TRUSTED_FW) && \ (defined(CFG_CORE_WORKAROUND_SPECTRE_BP) || \ @@ -239,8 +194,15 @@ END_FUNC reset_vect_table FUNC _start , : UNWIND( .cantunwind) - - bootargs_entry + /* + * Temporary copy of boot argument registers, will be passed to + * boot_save_args() further down. + */ + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + mov r8, lr /* * 32bit entry is expected to execute Supervisor mode, @@ -365,7 +327,7 @@ DECLARE_KEEP_INIT _start LOCAL_FUNC reset_primary , : , .identity_map UNWIND( .cantunwind) - /* preserve r4-r7: bootargs */ + /* preserve r4-r8: bootargs */ #ifdef CFG_WITH_PAGER /* @@ -390,8 +352,8 @@ UNWIND( .cantunwind) str r0, cached_mem_end ldr r2, =__init_start copy_init: - ldmdb r1!, {r3, r8-r12} - stmdb r0!, {r3, r8-r12} + ldmdb r1!, {r3, r9-r12} + stmdb r0!, {r3, r9-r12} cmp r0, r2 bgt copy_init #else @@ -411,8 +373,8 @@ copy_init: ldr r2, =__end copy_init: - ldmdb r1!, {r3, r8-r12} - stmdb r0!, {r3, r8-r12} + ldmdb r1!, {r3, r9-r12} + stmdb r0!, {r3, r9-r12} cmp r0, r2 bgt copy_init #endif @@ -480,6 +442,16 @@ shadow_stack_access_ok: /* Enable Console */ bl console_init + mov r0, r8 + mov r1, #0 + push {r0, r1} + mov r0, r4 + mov r1, r5 + mov r2, r6 + mov r3, r7 + bl boot_save_args + add sp, sp, #(2 * 4) + #ifdef CFG_PL310 bl pl310_base bl arm_cl2_config @@ -500,7 +472,6 @@ shadow_stack_access_ok: #endif #ifdef CFG_CORE_ASLR - mov r0, r6 bl get_aslr_seed #else mov r0, #0 @@ -547,8 +518,6 @@ shadow_stack_access_ok: bl core_mmu_set_default_prtn_tbl #endif - mov r0, r4 /* pageable part address */ - mov r1, r5 /* ns-entry address */ bl boot_init_primary_early #ifndef CFG_NS_VIRTUALIZATION mov r9, sp @@ -560,8 +529,6 @@ shadow_stack_access_ok: mov r0, #0 str r0, [r8, #THREAD_CORE_LOCAL_FLAGS] #endif - mov r0, r6 /* DT address */ - mov r1, #0 /* unused */ bl boot_init_primary_late #ifndef CFG_NS_VIRTUALIZATION mov r0, #THREAD_CLF_TMP @@ -633,10 +600,10 @@ shadow_stack_access_ok: /* Pass the vector address returned from main_init */ sub r1, r1, r0 #else - /* realy standard bootarg #1 and #2 to non secure entry */ + /* Relay standard bootarg #1 and #2 to non-secure entry */ mov r4, #0 mov r3, r6 /* std bootarg #2 for register R2 */ - mov r2, r7 /* std bootarg #1 for register R1 */ + mov r2, r5 /* std bootarg #1 for register R1 */ mov r1, #0 #endif /* CFG_WITH_ARM_TRUSTED_FW */ @@ -913,7 +880,7 @@ UNWIND( .cantunwind) bl boot_core_hpen ldm r0, {r0, r6} #else - mov r0, r5 /* ns-entry address */ + mov r0, r8 /* ns-entry address */ mov r6, #0 #endif bl boot_init_secondary diff --git a/core/arch/arm/kernel/entry_a64.S b/core/arch/arm/kernel/entry_a64.S index dd82e7106cb3e7a6a0b7cae74d452a21127f6a09..480ba7060046d7dc79dd3680a46605e8fce0e3b0 100644 --- a/core/arch/arm/kernel/entry_a64.S +++ b/core/arch/arm/kernel/entry_a64.S @@ -161,29 +161,13 @@ FUNC _start , : /* - * Register use: - * x0 - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n: - * if non-NULL holds the TOS FW config [1] address - * - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=y: - * address of FF-A Boot Information Blob - * - CFG_CORE_FFA=n: - * if non-NULL holds the pagable part address - * x2 - CFG_CORE_SEL2_SPMC=n: - * if non-NULL holds the system DTB address - * - * x19 - saved x0 - * x20 - saved x2 - * - * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware - * configuration file. Used by Trusted OS (BL32), that is, OP-TEE - * here. + * Temporary copy of boot argument registers, will be passed to + * boot_save_args() further down. */ mov x19, x0 -#if defined(CFG_DT_ADDR) - ldr x20, =CFG_DT_ADDR -#else - mov x20, x2 /* Save DT address */ -#endif + mov x20, x1 + mov x21, x2 + mov x22, x3 adr x0, reset_vect_table msr vbar_el1, x0 @@ -312,10 +296,12 @@ clear_nex_bss: /* Enable Console */ bl console_init -#if defined(CFG_CORE_SEL2_SPMC) - mov x0, x19 /* boot info */ - bl boot_save_boot_info -#endif + mov x0, x19 + mov x1, x20 + mov x2, x21 + mov x3, x22 + mov x4, xzr + bl boot_save_args #ifdef CFG_MEMTAG /* @@ -327,7 +313,6 @@ clear_nex_bss: #endif #ifdef CFG_CORE_ASLR - mov x0, x20 /* DT address */ bl get_aslr_seed #else mov x0, #0 @@ -376,12 +361,6 @@ clear_nex_bss: bl core_mmu_set_default_prtn_tbl #endif -#ifdef CFG_CORE_SEL1_SPMC - mov x0, xzr /* pager not used */ -#else - mov x0, x19 /* pagable part address */ -#endif - mov x1, #-1 bl boot_init_primary_early #ifdef CFG_MEMTAG @@ -389,19 +368,13 @@ clear_nex_bss: #endif #ifndef CFG_NS_VIRTUALIZATION - mov x21, sp + mov x23, sp adr_l x0, threads ldr x0, [x0, #THREAD_CTX_STACK_VA_END] mov sp, x0 bl thread_get_core_local - mov x22, x0 - str wzr, [x22, #THREAD_CORE_LOCAL_FLAGS] -#endif - mov x0, x20 /* DT address also known as HW_CONFIG */ -#ifdef CFG_CORE_SEL1_SPMC - mov x1, x19 /* TOS_FW_CONFIG DT address */ -#else - mov x1, xzr /* unused */ + mov x24, x0 + str wzr, [x24, #THREAD_CORE_LOCAL_FLAGS] #endif bl boot_init_primary_late #ifdef CFG_CORE_PAUTH @@ -410,8 +383,8 @@ clear_nex_bss: #ifndef CFG_NS_VIRTUALIZATION mov x0, #THREAD_CLF_TMP - str w0, [x22, #THREAD_CORE_LOCAL_FLAGS] - mov sp, x21 + str w0, [x24, #THREAD_CORE_LOCAL_FLAGS] + mov sp, x23 #endif #ifdef _CFG_CORE_STACK_PROTECTOR diff --git a/core/arch/arm/kernel/link_dummies_init.c b/core/arch/arm/kernel/link_dummies_init.c index 5c90271f785d6aec828c1fdf666096810427fcc3..c3617b2a8086d0cbcf71e641984178806588bba9 100644 --- a/core/arch/arm/kernel/link_dummies_init.c +++ b/core/arch/arm/kernel/link_dummies_init.c @@ -7,12 +7,14 @@ #include <mm/core_mmu.h> void __section(".text.dummy.boot_save_boot_info") -boot_save_boot_info(void *boot_info __unused) +boot_save_args(unsigned long a0 __unused, unsigned long a1 __unused, + unsigned long a2 __unused, unsigned long a3 __unused, + unsigned long a4 __unused) { } unsigned long __section(".text.dummy.get_aslr_seed") -get_aslr_seed(void *fdt __unused) +get_aslr_seed(void) { return 0; } @@ -24,7 +26,6 @@ core_init_mmu_map(unsigned long seed __unused, } void __section(".text.dummy.boot_init_primary_early") -boot_init_primary_early(unsigned long pageable_part __unused, - unsigned long nsec_entry __unused) +boot_init_primary_early(void) { } diff --git a/core/arch/arm/kernel/link_dummies_paged.c b/core/arch/arm/kernel/link_dummies_paged.c index d6d65c648fb52aebe77c1cca4c4d145e57c67969..4e9f090d019c16ba76f40a39ad7f9832a9ee23f2 100644 --- a/core/arch/arm/kernel/link_dummies_paged.c +++ b/core/arch/arm/kernel/link_dummies_paged.c @@ -29,7 +29,7 @@ void __section(".text.dummy.call_finalcalls") call_finalcalls(void) void __section(".text.dummy.boot_init_primary_late") boot_init_primary_late(unsigned long fdt __unused, - unsigned long manifest_dt __unused) + unsigned long manifest __unused) { } diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c index 87f9772191465724594e1dae25f6ca7343f2116a..65e0a82cbd36354c130c446c6ed661dad93355fb 100644 --- a/core/arch/arm/kernel/spmc_sp_handler.c +++ b/core/arch/arm/kernel/spmc_sp_handler.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2021-2023, Arm Limited + * Copyright (c) 2021-2024, Arm Limited */ #include <assert.h> #include <bench.h> @@ -500,6 +500,8 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer, if (ffa_vers <= FFA_VERSION_1_0) { struct ffa_mem_transaction_1_0 *d_ds = dst_buffer; + memset(d_ds, 0, sizeof(*d_ds)); + off = sizeof(*d_ds); mem_acc = d_ds->mem_access_array; @@ -512,6 +514,8 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer, } else { struct ffa_mem_transaction_1_1 *d_ds = dst_buffer; + memset(d_ds, 0, sizeof(*d_ds)); + off = sizeof(*d_ds); mem_acc = (void *)(d_ds + 1); @@ -533,6 +537,7 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer, sizeof(struct ffa_mem_access_perm)); /* Copy the mem_region_descr */ + memset(dst_region, 0, sizeof(*dst_region)); dst_region->address_range_count = 0; dst_region->total_page_count = 0; diff --git a/core/arch/arm/kernel/stmm_sp.c b/core/arch/arm/kernel/stmm_sp.c index 691bae845839be73fec48dea0449faadad790a63..6d991a3068abafe299c79478c4e75b620af2af67 100644 --- a/core/arch/arm/kernel/stmm_sp.c +++ b/core/arch/arm/kernel/stmm_sp.c @@ -663,7 +663,7 @@ static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id, sess = ts_get_current_session(); res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, - false, fops, &po); + TEE_POBJ_USAGE_OPEN, fops, &po); if (res != TEE_SUCCESS) return res; @@ -714,7 +714,7 @@ static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id, sess = ts_get_current_session(); res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, - false, fops, &po); + TEE_POBJ_USAGE_OPEN, fops, &po); if (res != TEE_SUCCESS) return res; diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk index 49c5927c3d500910fc18981324836bf669d28a92..c95c0bda34ccfece19d9bc1dbf07dbc6b5743992 100644 --- a/core/arch/arm/kernel/sub.mk +++ b/core/arch/arm/kernel/sub.mk @@ -24,7 +24,6 @@ endif ifeq ($(CFG_CORE_FFA),y) srcs-y += thread_spmc.c cppflags-thread_spmc.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) -srcs-$(CFG_ARM32_core) += thread_spmc_a32.S srcs-$(CFG_ARM64_core) += thread_spmc_a64.S else srcs-y += thread_optee_smc.c diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c index 66833b3a08645f24e30d682d313a7c27b31b482d..0dd9007ba63864289750f62dd2315a630c62084b 100644 --- a/core/arch/arm/kernel/thread.c +++ b/core/arch/arm/kernel/thread.c @@ -14,6 +14,7 @@ #include <keep.h> #include <kernel/asan.h> #include <kernel/boot.h> +#include <kernel/interrupt.h> #include <kernel/linker.h> #include <kernel/lockdep.h> #include <kernel/misc.h> diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c index bc69d8beac25f8ddd8b7804211232a4bdcf2d186..c1fcc23b36cdb7f5f41f84fd63dceab9ef8fe438 100644 --- a/core/arch/arm/kernel/thread_optee_smc.c +++ b/core/arch/arm/kernel/thread_optee_smc.c @@ -681,26 +681,21 @@ struct mobj *thread_rpc_alloc_payload(size_t size) struct mobj *thread_rpc_alloc_kernel_payload(size_t size) { - /* - * Error out early since kernel private dynamic shared memory - * allocations don't currently use the `OPTEE_MSG_ATTR_NONCONTIG` bit - * and therefore cannot be larger than a page. - */ - if (IS_ENABLED(CFG_CORE_DYN_SHM) && size > SMALL_PAGE_SIZE) - return NULL; - return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); } void thread_rpc_free_kernel_payload(struct mobj *mobj) { - thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, + mobj_get_cookie(mobj), mobj); } void thread_rpc_free_payload(struct mobj *mobj) { - thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), - mobj); + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), + mobj); } struct mobj *thread_rpc_alloc_global_payload(size_t size) diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c index 59cdb51b14df27a5c1b5fc54c116e3e761190bcb..dd63f82575ff91131e3f86cd96c0361458c96dca 100644 --- a/core/arch/arm/kernel/thread_spmc.c +++ b/core/arch/arm/kernel/thread_spmc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2020-2021, Linaro Limited. + * Copyright (c) 2020-2023, Linaro Limited. * Copyright (c) 2019-2021, Arm Limited. All rights reserved. */ @@ -9,6 +9,7 @@ #include <initcall.h> #include <io.h> #include <kernel/interrupt.h> +#include <kernel/notif.h> #include <kernel/panic.h> #include <kernel/secure_partition.h> #include <kernel/spinlock.h> @@ -46,6 +47,11 @@ struct mem_frag_state { }; #endif +static unsigned int spmc_notif_lock = SPINLOCK_UNLOCK; +static int do_bottom_half_value = -1; +static uint16_t notif_vm_id; +static bool spmc_notif_is_ready; + /* Initialized in spmc_init() below */ static uint16_t my_endpoint_id __nex_bss; #ifdef CFG_CORE_SEL1_SPMC @@ -96,6 +102,11 @@ static bool is_nw_buf(struct ffa_rxtx *rxtx) static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head = SLIST_HEAD_INITIALIZER(&frag_state_head); + +static uint64_t notif_pending_bitmap; +static uint64_t notif_bound_bitmap; +static bool notif_vm_id_valid; +static int notif_intid = -1; #else static uint8_t __rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); static uint8_t __tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); @@ -146,10 +157,17 @@ uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx) #if defined(CFG_CORE_SEL1_SPMC) static void handle_features(struct thread_smc_args *args) { - uint32_t ret_fid = 0; - uint32_t ret_w2 = FFA_PARAM_MBZ; + uint32_t ret_fid = FFA_ERROR; + uint32_t ret_w2 = FFA_NOT_SUPPORTED; switch (args->a1) { + case FFA_FEATURE_SCHEDULE_RECV_INTR: + if (spmc_notif_is_ready) { + ret_fid = FFA_SUCCESS_32; + ret_w2 = notif_intid; + } + break; + #ifdef ARM64 case FFA_RXTX_MAP_64: #endif @@ -187,11 +205,20 @@ static void handle_features(struct thread_smc_args *args) case FFA_RXTX_UNMAP: case FFA_RX_RELEASE: case FFA_FEATURE_MANAGED_EXIT_INTR: + case FFA_NOTIFICATION_BITMAP_CREATE: + case FFA_NOTIFICATION_BITMAP_DESTROY: + case FFA_NOTIFICATION_BIND: + case FFA_NOTIFICATION_UNBIND: + case FFA_NOTIFICATION_SET: + case FFA_NOTIFICATION_GET: + case FFA_NOTIFICATION_INFO_GET_32: +#ifdef ARM64 + case FFA_NOTIFICATION_INFO_GET_64: +#endif ret_fid = FFA_SUCCESS_32; + ret_w2 = FFA_PARAM_MBZ; break; default: - ret_fid = FFA_ERROR; - ret_w2 = FFA_NOT_SUPPORTED; break; } @@ -474,6 +501,7 @@ void spmc_handle_partition_info_get(struct thread_smc_args *args, { TEE_Result res = TEE_SUCCESS; uint32_t ret_fid = FFA_ERROR; + uint32_t fpi_size = 0; uint32_t rc = 0; bool count_only = args->a5 & FFA_PARTITION_INFO_GET_COUNT_FLAG; @@ -547,7 +575,11 @@ void spmc_handle_partition_info_get(struct thread_smc_args *args, ret_fid = FFA_SUCCESS_32; out: - spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ, + if (ret_fid == FFA_SUCCESS_32 && !count_only && + rxtx->ffa_vers >= FFA_VERSION_1_1) + fpi_size = sizeof(struct ffa_partition_info_x) + FFA_UUID_SIZE; + + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, fpi_size, FFA_PARAM_MBZ, FFA_PARAM_MBZ); if (!count_only) { rxtx->tx_is_mine = false; @@ -582,6 +614,30 @@ out: } #endif /*CFG_CORE_SEL1_SPMC*/ +static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value, + uint16_t vm_id) +{ + uint32_t old_itr_status = 0; + + if (!spmc_notif_is_ready) { + /* + * This should never happen, not if normal world respects the + * exchanged capabilities. + */ + EMSG("Asynchronous notifications are not ready"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + do_bottom_half_value = bottom_half_value; + if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) + notif_vm_id = vm_id; + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + + notif_deliver_atomic_event(NOTIF_EVENT_STARTED); + return TEE_SUCCESS; +} + static void handle_yielding_call(struct thread_smc_args *args, uint32_t direct_resp_fid) { @@ -630,6 +686,8 @@ static uint32_t handle_unregister_shm(uint32_t a4, uint32_t a5) static void handle_blocking_call(struct thread_smc_args *args, uint32_t direct_resp_fid) { + uint32_t sec_caps = 0; + switch (args->a3) { case OPTEE_FFA_GET_API_VERSION: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, @@ -642,14 +700,24 @@ static void handle_blocking_call(struct thread_smc_args *args, CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1); break; case OPTEE_FFA_EXCHANGE_CAPABILITIES: - spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, - 0, THREAD_RPC_MAX_NUM_PARAMS, - OPTEE_FFA_SEC_CAP_ARG_OFFSET); + sec_caps = OPTEE_FFA_SEC_CAP_ARG_OFFSET; + if (spmc_notif_is_ready) + sec_caps |= OPTEE_FFA_SEC_CAP_ASYNC_NOTIF; + spmc_set_args(args, direct_resp_fid, + swap_src_dst(args->a1), 0, 0, + THREAD_RPC_MAX_NUM_PARAMS, sec_caps); break; case OPTEE_FFA_UNREGISTER_SHM: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, handle_unregister_shm(args->a4, args->a5), 0, 0); break; + case OPTEE_FFA_ENABLE_ASYNC_NOTIF: + spmc_set_args(args, direct_resp_fid, + swap_src_dst(args->a1), 0, + spmc_enable_async_notif(args->a4, + FFA_SRC(args->a1)), + 0, 0); + break; default: EMSG("Unhandled blocking service ID %#"PRIx32, (uint32_t)args->a3); @@ -1302,7 +1370,223 @@ static void handle_mem_reclaim(struct thread_smc_args *args) virt_unset_guest(); out: - spmc_set_args(args, ret_fid, ret_val, 0, 0, 0, 0); + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_bitmap_create(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + + if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && + !args->a5 && !args->a6 && !args->a7) { + uint16_t vm_id = args->a1; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid) { + if (vm_id == notif_vm_id) + ret_val = FFA_DENIED; + else + ret_val = FFA_NO_MEMORY; + } else { + notif_vm_id = vm_id; + notif_vm_id_valid = true; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + } + + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_bitmap_destroy(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + + if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && + !args->a5 && !args->a6 && !args->a7) { + uint16_t vm_id = args->a1; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + if (notif_pending_bitmap || notif_bound_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_vm_id_valid = false; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + } + + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_bind(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint64_t bitmap = 0; + uint16_t vm_id = 0; + + if (args->a5 || args->a6 || args->a7) + goto out; + if (args->a2) { + /* We only deal with global notifications for now */ + ret_val = FFA_NOT_SUPPORTED; + goto out; + } + + /* The destination of the eventual notification */ + vm_id = FFA_DST(args->a1); + bitmap = reg_pair_to_64(args->a4, args->a3); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + if (bitmap & notif_bound_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_bound_bitmap |= bitmap; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_unbind(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint64_t bitmap = 0; + uint16_t vm_id = 0; + + if (args->a2 || args->a5 || args->a6 || args->a7) + goto out; + + /* The destination of the eventual notification */ + vm_id = FFA_DST(args->a1); + bitmap = reg_pair_to_64(args->a4, args->a3); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + /* + * Spec says: + * At least one notification is bound to another Sender or + * is currently pending. + * + * Not sure what the intention is. + */ + if (bitmap & notif_pending_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_bound_bitmap &= ~bitmap; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_get(struct thread_smc_args *args) +{ + uint32_t w2 = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint16_t vm_id = 0; + uint32_t w3 = 0; + + if (args->a5 || args->a6 || args->a7) + goto out; + if (!(args->a2 & 0x1)) { + ret_fid = FFA_SUCCESS_32; + w2 = 0; + goto out; + } + vm_id = FFA_DST(args->a1); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + reg_pair_from_64(notif_pending_bitmap, &w3, &w2); + notif_pending_bitmap = 0; + ret_fid = FFA_SUCCESS_32; + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, w2, w3, 0, 0); +} + +static void handle_notification_info_get(struct thread_smc_args *args) +{ + uint32_t w2 = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + + if (args->a1 || args->a2 || args->a3 || args->a4 || args->a5 || + args->a6 || args->a7) + goto out; + + if (OPTEE_SMC_IS_64(args->a0)) + ret_fid = FFA_SUCCESS_64; + else + ret_fid = FFA_SUCCESS_32; + + /* + * Note, we're only supporting physical OS kernel in normal world + * with Global Notifications. + * So one list of ID list registers (BIT[11:7]) + * and one count of IDs (BIT[13:12] + 1) + * and the VM is always 0. + */ + w2 = SHIFT_U32(1, 7); +out: + spmc_set_args(args, ret_fid, 0, w2, 0, 0, 0); +} + +void thread_spmc_set_async_notif_intid(int intid) +{ + assert(interrupt_can_raise_sgi(interrupt_get_main_chip())); + notif_intid = intid; + spmc_notif_is_ready = true; + DMSG("Asynchronous notifications are ready"); +} + +void notif_send_async(uint32_t value) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready && + do_bottom_half_value >= 0 && notif_intid >= 0); + notif_pending_bitmap |= BIT64(do_bottom_half_value); + interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid, + ITR_CPU_MASK_TO_THIS_CPU); + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +} +#else +void __noreturn notif_send_async(uint32_t value __unused) +{ + panic(); } #endif @@ -1367,7 +1651,40 @@ void thread_spmc_msg_recv(struct thread_smc_args *args) case FFA_MEM_FRAG_TX: handle_mem_frag_tx(args, &my_rxtx); break; + case FFA_NOTIFICATION_BITMAP_CREATE: + handle_notification_bitmap_create(args); + break; + case FFA_NOTIFICATION_BITMAP_DESTROY: + handle_notification_bitmap_destroy(args); + break; + case FFA_NOTIFICATION_BIND: + handle_notification_bind(args); + break; + case FFA_NOTIFICATION_UNBIND: + handle_notification_unbind(args); + break; + case FFA_NOTIFICATION_GET: + handle_notification_get(args); + break; +#ifdef ARM64 + case FFA_NOTIFICATION_INFO_GET_64: +#endif + case FFA_NOTIFICATION_INFO_GET_32: + handle_notification_info_get(args); + break; #endif /*CFG_CORE_SEL1_SPMC*/ + case FFA_ERROR: + EMSG("Cannot handle FFA_ERROR(%d)", (int)args->a2); + if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) { + /* + * The SPMC will return an FFA_ERROR back so better + * panic() now than flooding the log. + */ + panic("FFA_ERROR from SPMC is fatal"); + } + spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); + break; default: EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0); spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED, @@ -1654,13 +1971,16 @@ struct mobj *thread_rpc_alloc_kernel_payload(size_t size) void thread_rpc_free_kernel_payload(struct mobj *mobj) { - thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, + mobj_get_cookie(mobj), mobj); } void thread_rpc_free_payload(struct mobj *mobj) { - thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), - mobj); + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), + mobj); } struct mobj *thread_rpc_alloc_global_payload(size_t size) @@ -1670,8 +1990,9 @@ struct mobj *thread_rpc_alloc_global_payload(size_t size) void thread_rpc_free_global_payload(struct mobj *mobj) { - thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), - mobj); + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, + mobj_get_cookie(mobj), mobj); } void thread_spmc_register_secondary_ep(vaddr_t ep) diff --git a/core/arch/arm/kernel/thread_spmc_a32.S b/core/arch/arm/kernel/thread_spmc_a32.S deleted file mode 100644 index 7a8d9da988066f8122adbd54d12f4718303c0644..0000000000000000000000000000000000000000 --- a/core/arch/arm/kernel/thread_spmc_a32.S +++ /dev/null @@ -1,136 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ -/* - * Copyright (c) 2020, Linaro Limited - */ - -#include <platform_config.h> - -#include <arm32_macros.S> -#include <arm.h> -#include <asm.S> -#include <ffa.h> -#include <generated/asm-defines.h> -#include <kernel/thread.h> -#include <optee_ffa.h> - -FUNC thread_ffa_msg_wait , : - mov_imm r0, FFA_MSG_WAIT /* FID */ - mov r1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */ - mov r2, #FFA_PARAM_MBZ /* Param MBZ */ - mov r3, #FFA_PARAM_MBZ /* Param MBZ */ - mov r4, #FFA_PARAM_MBZ /* Param MBZ */ - mov r5, #FFA_PARAM_MBZ /* Param MBZ */ - mov r6, #FFA_PARAM_MBZ /* Param MBZ */ - mov r7, #FFA_PARAM_MBZ /* Param MBZ */ - b .ffa_msg_loop -END_FUNC thread_ffa_msg_wait - - /* Caller provides r1, r3-r7 params */ -LOCAL_FUNC ffa_msg_send_direct_resp , : - ldr r0, =FFA_MSG_SEND_DIRECT_RESP_32 /* FID */ - mov r2, #FFA_PARAM_MBZ /* RES MBZ */ - -.ffa_msg_loop: - /* Invoke SMC with caller provided parameters */ - smc #0 - - /* Store the parameters as struct thread_smc_args on stack */ - push {r0-r7} - mov r0, sp - - /* parse and handle message */ - bl thread_spmc_msg_recv - - /* Load struct thread_smc_args into registers */ - pop {r0-r7} - b .ffa_msg_loop -END_FUNC ffa_msg_send_direct_resp - -FUNC thread_std_smc_entry , : -UNWIND( .cantunwind) - - push {r4, r5} /* Pass these following the arm32 calling convention */ - ror r4, r0, #16 /* Save target info with src and dst swapped */ - bl __thread_std_smc_entry - add sp, sp, #8 /* There's nothing return, just restore the sp */ - mov r5, r0 /* Save return value */ - - /* Mask all maskable exceptions before switching to temporary stack */ - cpsid aif - bl thread_get_tmp_sp - mov sp, r0 - - bl thread_state_free - - mov r1, r4 /* Target info */ - mov r3, r5 /* Return value */ - mov r4, #FFA_PARAM_MBZ /* Unused parameter */ - mov r5, #FFA_PARAM_MBZ /* Unused parameter */ - mov r6, #FFA_PARAM_MBZ /* Unused parameter */ - mov r7, #FFA_PARAM_MBZ /* Unused parameter */ - b ffa_msg_send_direct_resp -END_FUNC thread_std_smc_entry - -/* void thread_rpc(struct thread_rpc_arg *rpc_arg) */ -FUNC thread_rpc , : - push {r0, lr} -UNWIND( .save {r0, lr}) - - bl thread_save_state - mov r4, r0 /* Save original CPSR */ - - /* - * Switch to temporary stack and SVC mode. Save CPSR to resume into. - */ - bl thread_get_tmp_sp - ldr r8, [sp] /* Get pointer to rv[] */ - cps #CPSR_MODE_SVC /* Change to SVC mode */ - mov sp, r0 /* Switch to tmp stack */ - - mov r0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN - mov r1, r4 /* CPSR to restore */ - ldr r2, =.thread_rpc_return - bl thread_state_suspend - mov r7, r0 /* Supply thread index */ - ldr r0, =FFA_MSG_SEND_DIRECT_RESP_32 - mov r2, #FFA_PARAM_MBZ - mov r3, #0 /* Error code = 0 */ - ldm r8, {r1, r4-r6} /* Load rv[] into r1,r4-r6 */ - b ffa_msg_send_direct_resp - -.thread_rpc_return: - /* - * At this point has the stack pointer been restored to the value - * it had when thread_save_state() was called above. - * - * Jumps here from thread_resume above when RPC has returned. The - * IRQ and FIQ bits are restored to what they where when this - * function was originally entered. - */ - pop {r12, lr} /* Get pointer to rv[] */ - stm r12, {r0-r3} /* Store r0-r3 into rv[] */ - bx lr -END_FUNC thread_rpc - -/* - * void thread_foreign_intr_exit(uint32_t thread_index) - * - * This function is jumped to at the end of macro foreign_intr_handler(). - * The current thread as indicated by @thread_index has just been - * suspended. The job here is just to inform normal world the thread id to - * resume when returning. - */ -FUNC thread_foreign_intr_exit , : - /* load threads[r0].tsd.rpc_target_info into r1 */ - mov r1, #THREAD_CTX_SIZE - ldr r2, =threads - mla r1, r1, r0, r2 - ldr r1, [r1, #THREAD_CTX_TSD_RPC_TARGET_INFO] - mov r2, #FFA_PARAM_MBZ - mov r3, #FFA_PARAM_MBZ - mov r4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT - mov r5, #FFA_PARAM_MBZ - mov r6, #FFA_PARAM_MBZ - mov r7, r0 - b ffa_msg_send_direct_resp -END_FUNC thread_foreign_intr_exit diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S index 8ea2bce5f520eea722f7cac12f97cb571d144476..46f241c9f0571e67474b6d58338aa20de94d7136 100644 --- a/core/arch/arm/kernel/thread_spmc_a64.S +++ b/core/arch/arm/kernel/thread_spmc_a64.S @@ -14,7 +14,7 @@ #include <kernel/thread.h> #include <optee_ffa.h> -#if CFG_SECURE_PARTITION +#ifdef CFG_SECURE_PARTITION LOCAL_FUNC thread_ffa_interrupt , : mov_imm x0, FFA_INTERRUPT /* FID */ /* X1: Endpoint/vCPU IDs is set by caller */ @@ -197,7 +197,7 @@ FUNC thread_foreign_intr_exit , : adr_l x2, threads madd x2, x1, x0, x2 ldr w1, [x2, #THREAD_CTX_TSD_RPC_TARGET_INFO] -#if CFG_SECURE_PARTITION +#ifdef CFG_SECURE_PARTITION /* load threads[w0].flags into w2 */ ldr w2, [x2, #THREAD_CTX_FLAGS] and w2, w2, #THREAD_FLAGS_FFA_ONLY diff --git a/core/arch/arm/kernel/tz_ssvce_pl310_a32.S b/core/arch/arm/kernel/tz_ssvce_pl310_a32.S index b3f85cc168c0a6e814c39e84f01438f53b8bdb3a..c5c94e7817d7eeda026055364479756eaed4d055 100644 --- a/core/arch/arm/kernel/tz_ssvce_pl310_a32.S +++ b/core/arch/arm/kernel/tz_ssvce_pl310_a32.S @@ -222,3 +222,14 @@ FUNC arm_cl2_cleaninvbypa , : b _arm_cl2_xxxbypa END_FUNC arm_cl2_cleaninvbypa +/* + * __weak vaddr_t pl310_nsbase(void); + * return the non-secure PL310 base address + * + * Weak implementation to preserve the previous behavior where only the + * secure PL310 base address was returned. Up to the platform to map + * and return non-secure PL310 base address. + */ +WEAK_FUNC pl310_nsbase , : + b pl310_base +END_FUNC pl310_nsbase diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c index e25f5cc510eeedd7976d80fba3ff85cc89830745..0b6af6ad06388ed12da7ec4a25754e6aceb8777a 100644 --- a/core/arch/arm/mm/core_mmu.c +++ b/core/arch/arm/mm/core_mmu.c @@ -14,6 +14,7 @@ #include <kernel/tee_misc.h> #include <kernel/tlb_helpers.h> #include <kernel/tz_ssvce_pl310.h> +#include <mm/core_memprot.h> #include <mm/core_mmu.h> #include <platform_config.h> #include <trace.h> @@ -99,6 +100,26 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) { TEE_Result ret = TEE_SUCCESS; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + vaddr_t pl310_base_pa_op = 0; + + /* + * According the ARM PL310 documentation, if the operation is specific + * to the PA, the behavior is presented in the following manner: + * - Secure access: The data in the cache is only affected by the + * operation if it is secure. + * - Non-secure access: The data in the cache is only affected by the + * operation if it is non-secure. + * + * https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations + * + * Depending on the buffer location, use the secure or non-secure PL310 + * base address to do physical address based cache operation on the + * buffer. + */ + if (tee_pbuf_is_sec(pa, len)) + pl310_base_pa_op = pl310_base(); + else + pl310_base_pa_op = pl310_nsbase(); tee_l2cc_mutex_lock(); switch (op) { @@ -107,21 +128,22 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) break; case DCACHE_AREA_INVALIDATE: if (len) - arm_cl2_invbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_invbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN: arm_cl2_cleanbyway(pl310_base()); break; case DCACHE_AREA_CLEAN: if (len) - arm_cl2_cleanbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_cleanbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN_INV: arm_cl2_cleaninvbyway(pl310_base()); break; case DCACHE_AREA_CLEAN_INV: if (len) - arm_cl2_cleaninvbypa(pl310_base(), pa, pa + len - 1); + arm_cl2_cleaninvbypa(pl310_base_pa_op, pa, + pa + len - 1); break; default: ret = TEE_ERROR_NOT_IMPLEMENTED; diff --git a/core/arch/arm/mm/core_mmu_lpae.c b/core/arch/arm/mm/core_mmu_lpae.c index 7e79f780ad28984a6ec1f46e44457367fb5c72b3..dffbda8d094f615d27882ee306468d8cf174b647 100644 --- a/core/arch/arm/mm/core_mmu_lpae.c +++ b/core/arch/arm/mm/core_mmu_lpae.c @@ -141,6 +141,7 @@ #define TCR_PS_BITS_4TB (0x3) #define TCR_PS_BITS_16TB (0x4) #define TCR_PS_BITS_256TB (0x5) +#define TCR_PS_BITS_4PB (0x6) #define UNSET_DESC ((uint64_t)-1) @@ -866,7 +867,7 @@ void core_init_mmu_regs(struct core_mmu_config *cfg) #endif /*ARM32*/ #ifdef ARM64 -static unsigned int get_physical_addr_size_bits(void) +static unsigned int get_hard_coded_pa_size_bits(void) { /* * Intermediate Physical Address Size. @@ -876,10 +877,10 @@ static unsigned int get_physical_addr_size_bits(void) * 0b011 42 bits, 4TB. * 0b100 44 bits, 16TB. * 0b101 48 bits, 256TB. - * 0b110 52 bits, 4PB (not supported) + * 0b110 52 bits, 4PB */ - - COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS >= 32); + static_assert(CFG_CORE_ARM64_PA_BITS >= 32); + static_assert(CFG_CORE_ARM64_PA_BITS <= 52); if (CFG_CORE_ARM64_PA_BITS <= 32) return TCR_PS_BITS_4GB; @@ -896,10 +897,34 @@ static unsigned int get_physical_addr_size_bits(void) if (CFG_CORE_ARM64_PA_BITS <= 44) return TCR_PS_BITS_16TB; - /* Physical address can't exceed 48 bits */ - COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS <= 48); + if (CFG_CORE_ARM64_PA_BITS <= 48) + return TCR_PS_BITS_256TB; + /* CFG_CORE_ARM64_PA_BITS <= 48 */ - return TCR_PS_BITS_256TB; + return TCR_PS_BITS_4PB; +} + +static unsigned int get_physical_addr_size_bits(void) +{ + const unsigned int size_bits = read_id_aa64mmfr0_el1() & + ID_AA64MMFR0_EL1_PARANGE_MASK; + unsigned int b = 0; + + if (IS_ENABLED(CFG_AUTO_MAX_PA_BITS)) + return size_bits; + + b = get_hard_coded_pa_size_bits(); + assert(b <= size_bits); + return b; +} + +unsigned int core_mmu_arm64_get_pa_width(void) +{ + const uint8_t map[] = { 32, 36, 40, 42, 44, 48, 52, }; + unsigned int size_bits = get_physical_addr_size_bits(); + + size_bits = MIN(size_bits, ARRAY_SIZE(map) - 1); + return map[size_bits]; } void core_init_mmu_regs(struct core_mmu_config *cfg) diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c index e57c95ac83cd718168f0ba2efeb7e49cb43e6bc5..8d3d71447fe2399176e09551fa7718920e26a7d2 100644 --- a/core/arch/arm/mm/mobj_ffa.c +++ b/core/arch/arm/mm/mobj_ffa.c @@ -423,7 +423,17 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie) } #if defined(CFG_CORE_SEL1_SPMC) if (!mf->registered_by_cookie) { - EMSG("cookie %#"PRIx64" not registered", cookie); + /* + * This is expected behaviour if the normal world has + * registered the memory but OP-TEE has not yet used the + * corresponding cookie with mobj_ffa_get_by_cookie(). It + * can be non-trivial for the normal world to predict if + * the cookie really has been used or not. So even if we + * return it as an error it will be ignored by + * handle_unregister_shm(). + */ + EMSG("cookie %#"PRIx64" not registered refs %u:%u", + cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } diff --git a/core/arch/arm/plat-aspeed/conf.mk b/core/arch/arm/plat-aspeed/conf.mk index a45ccca95ac6bf970b4ce9207f9a0e8ea9c4a4fc..d3249e2e3200e5c07213a9882b29304a33ade0a8 100644 --- a/core/arch/arm/plat-aspeed/conf.mk +++ b/core/arch/arm/plat-aspeed/conf.mk @@ -18,6 +18,8 @@ CFG_TZDRAM_START ?= 0xb0000000 CFG_TZDRAM_SIZE ?= 0x1000000 CFG_CORE_RESERVED_SHM ?= n + +arm32-platform-cflags += -mfpu=vfpv3-d16 else ifeq ($(PLATFORM_FLAVOR),ast2700) include core/arch/arm/cpu/cortex-armv8-0.mk diff --git a/core/arch/arm/plat-aspeed/platform_ast2600.c b/core/arch/arm/plat-aspeed/platform_ast2600.c index f8b359c8060df2c352f201dd65ed2fda72e34255..b6132c0229b3ef28ed12e7377fe04fe0ec95cdf6 100644 --- a/core/arch/arm/plat-aspeed/platform_ast2600.c +++ b/core/arch/arm/plat-aspeed/platform_ast2600.c @@ -67,7 +67,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } void console_init(void) diff --git a/core/arch/arm/plat-aspeed/platform_ast2700.c b/core/arch/arm/plat-aspeed/platform_ast2700.c index a1b3ac42c0e859c320048a7e5eb533e7bef6fe36..106c88df173c4bd7fdc582a34df2b26ae7cbcb73 100644 --- a/core/arch/arm/plat-aspeed/platform_ast2700.c +++ b/core/arch/arm/plat-aspeed/platform_ast2700.c @@ -13,6 +13,7 @@ register_phys_mem(MEM_AREA_IO_SEC, UART_BASE, SMALL_PAGE_SIZE); register_phys_mem(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, GICR_BASE, GICR_SIZE); register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); @@ -20,12 +21,12 @@ static struct serial8250_uart_data console_data; void boot_primary_init_intc(void) { - gic_init(0, GICD_BASE); + gic_init_v3(0, GICD_BASE, GICR_BASE); } void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } void console_init(void) diff --git a/core/arch/arm/plat-aspeed/platform_config.h b/core/arch/arm/plat-aspeed/platform_config.h index 69f26793db29ba925a4631345b5cb5bcdc392492..c6b322fac16bfb46e6a6e5c53f6a4e1f96d6df81 100644 --- a/core/arch/arm/plat-aspeed/platform_config.h +++ b/core/arch/arm/plat-aspeed/platform_config.h @@ -26,6 +26,7 @@ #elif defined(PLATFORM_FLAVOR_ast2700) #define GICD_BASE 0x12200000 #define GICR_BASE 0x12280000 +#define GICR_SIZE 0x100000 #define UART_BASE 0x14c33000 #define UART12_BASE (UART_BASE + 0xb00) diff --git a/core/arch/arm/plat-corstone1000/main.c b/core/arch/arm/plat-corstone1000/main.c index 846b60116a850d3eee9990c2dab2210b4e743e91..b3861c4c88f7049cb537ace23446251a64c9832d 100644 --- a/core/arch/arm/plat-corstone1000/main.c +++ b/core/arch/arm/plat-corstone1000/main.c @@ -28,7 +28,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } void console_init(void) diff --git a/core/arch/arm/plat-d06/conf.mk b/core/arch/arm/plat-d06/conf.mk index 98a8fa01bbe74e04598901cb86fc3eefb8242d1c..7c250a7c30465687c271a5881f752fcc720e7530 100644 --- a/core/arch/arm/plat-d06/conf.mk +++ b/core/arch/arm/plat-d06/conf.mk @@ -5,9 +5,10 @@ CFG_NUM_THREADS ?= 96 CFG_CRYPTO_WITH_CE ?= y CFG_WITH_PAGER ?= n -CFG_WITH_SOFTWARE_PRNG ?= y +CFG_WITH_SOFTWARE_PRNG ?= n CFG_WITH_STATS ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y +CFG_HISILICON_CRYPTO_DRIVER ?= y $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) @@ -26,3 +27,4 @@ CFG_TZDRAM_START ?= 0x20C0000000 CFG_TZDRAM_SIZE ?= 0x32000000 CFG_SHMEM_START ?= 0x50000000 CFG_SHMEM_SIZE ?= 0x04000000 + diff --git a/core/arch/arm/plat-d06/platform_config.h b/core/arch/arm/plat-d06/platform_config.h index 81979bdc478cae37c772a61b0bff2341ff8a38b3..3ca0a0f49543239e98b9ca1d0b5761c6b7870a78 100644 --- a/core/arch/arm/plat-d06/platform_config.h +++ b/core/arch/arm/plat-d06/platform_config.h @@ -17,4 +17,8 @@ #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 200 +/* HISI_TRNG */ +#define HISI_TRNG_BASE 0x2010C0000 +#define HISI_TRNG_SIZE 0x100 + #endif /* PLATFORM_CONFIG_H */ diff --git a/core/arch/arm/plat-hikey/main.c b/core/arch/arm/plat-hikey/main.c index 9e0543a7ceb37c4098f0b9b487f535a0ea2d12d8..239072db5bc86c8c4593a3de3e6b2050994b729d 100644 --- a/core/arch/arm/plat-hikey/main.c +++ b/core/arch/arm/plat-hikey/main.c @@ -60,14 +60,14 @@ void spi_init(void) vaddr_t pmx1_base = core_mmu_get_va(PMX1_BASE, MEM_AREA_IO_NSEC, PMX1_REG_SIZE); - DMSG("take SPI0 out of reset\n"); + DMSG("take SPI0 out of reset"); shifted_val = PERI_RST3_SSP; /* * no need to read PERI_SC_PERIPH_RSTDIS3 first * as all the bits are processed and cleared after writing */ io_write32(peri_base + PERI_SC_PERIPH_RSTDIS3, shifted_val); - DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x\n", + DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_RSTDIS3)); /* @@ -77,19 +77,19 @@ void spi_init(void) do { read_val = io_read32(peri_base + PERI_SC_PERIPH_RSTSTAT3); } while (read_val & shifted_val); - DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x\n", read_val); + DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x", read_val); - DMSG("enable SPI clock\n"); + DMSG("enable SPI clock"); /* * no need to read PERI_SC_PERIPH_CLKEN3 first * as all the bits are processed and cleared after writing */ shifted_val = PERI_CLK3_SSP; io_write32(peri_base + PERI_SC_PERIPH_CLKEN3, shifted_val); - DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x\n", + DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_CLKEN3)); - DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x\n", + DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_CLKSTAT3)); /* @@ -101,13 +101,13 @@ void spi_init(void) * transfer. * ref: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/CJACFAFG.html */ - DMSG("configure gpio6 pins 0-3 as SPI\n"); + DMSG("configure gpio6 pins 0-3 as SPI"); io_write32(pmx0_base + PMX0_IOMG104, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG105, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG107, PINMUX_SPI); - DMSG("configure gpio6 pins 0-3 as nopull\n"); + DMSG("configure gpio6 pins 0-3 as nopull"); io_write32(pmx1_base + PMX1_IOCG104, PINCFG_NOPULL); io_write32(pmx1_base + PMX1_IOCG105, PINCFG_NOPULL); io_write32(pmx1_base + PMX1_IOCG106, PINCFG_NOPULL); @@ -124,7 +124,7 @@ static TEE_Result peripherals_init(void) vaddr_t pmussi_base = core_mmu_get_va(PMUSSI_BASE, MEM_AREA_IO_NSEC, PMUSSI_REG_SIZE); - DMSG("enable LD021_1V8 source (pin 35) on LS connector\n"); + DMSG("enable LD021_1V8 source (pin 35) on LS connector"); /* * Mezzanine cards usually use this to source level shifters for * UART, GPIO, SPI, I2C, etc so if not enabled, connected diff --git a/core/arch/arm/plat-hikey/spi_test.c b/core/arch/arm/plat-hikey/spi_test.c index ea7ec25875ab9c2b439546b31b647819d29febc7..5b43da64b679b0be33a2b1e7e6d4f0dd2d5d9132 100644 --- a/core/arch/arm/plat-hikey/spi_test.c +++ b/core/arch/arm/plat-hikey/spi_test.c @@ -80,7 +80,7 @@ static void spi_test_with_manual_cs_control(void) DMSG("Set CS callback"); pd.cs_control = PL022_CS_CTRL_MANUAL; - DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd.base = spi_base; pd.clk_hz = SPI_CLK_HZ; @@ -170,7 +170,7 @@ static void spi_test_with_registered_cs_cb(void) pd.cs_data.cs_cb = spi_cs_callback; pd.cs_control = PL022_CS_CTRL_CB; - DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd.base = spi_base; pd.clk_hz = SPI_CLK_HZ; @@ -215,7 +215,7 @@ static void spi_test_with_builtin_cs_control(void) spi_set_cs_mux(PINMUX_GPIO); - DMSG("gpio6_base: 0x%" PRIxVA "\n", gpio6_base); + DMSG("gpio6_base: 0x%" PRIxVA, gpio6_base); DMSG("Configure GPIO"); pl061_init(&pd061); pl061_register(gpio6_base, 6); @@ -226,7 +226,7 @@ static void spi_test_with_builtin_cs_control(void) pd022.cs_data.gpio_data.pin_num = GPIO6_2; pd022.cs_control = PL022_CS_CTRL_AUTO_GPIO; - DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd022.base = spi_base; pd022.clk_hz = SPI_CLK_HZ; diff --git a/core/arch/arm/plat-imx/conf.mk b/core/arch/arm/plat-imx/conf.mk index 4e85e52cc8911b2eb628ed769f520cfe8be38f96..85bbfe5032a95f8aae2020921a97d2944ca58b27 100644 --- a/core/arch/arm/plat-imx/conf.mk +++ b/core/arch/arm/plat-imx/conf.mk @@ -78,6 +78,7 @@ mx8qm-flavorlist = \ mx8qx-flavorlist = \ mx8qxpmek \ + mx8dxmek \ mx8dxl-flavorlist = \ mx8dxlevk \ @@ -216,7 +217,7 @@ CFG_TEE_CORE_NB_CORE ?= 2 $(call force,CFG_NXP_SNVS,n) $(call force,CFG_IMX_OCOTP,n) CFG_IMX_MU ?= y -CFG_IMX_ELE ?= y +CFG_IMX_ELE ?= n else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx93-flavorlist))) $(call force,CFG_MX93,y) $(call force,CFG_ARM64_core,y) @@ -229,7 +230,7 @@ $(call force,CFG_TZC380,n) $(call force,CFG_CRYPTO_DRIVER,n) $(call force,CFG_NXP_CAAM,n) CFG_IMX_MU ?= y -CFG_IMX_ELE ?= y +CFG_IMX_ELE ?= n else $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") endif @@ -398,6 +399,12 @@ CFG_NSEC_DDR_1_SIZE ?= 0x380000000UL CFG_CORE_ARM64_PA_BITS ?= 40 endif +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxmek)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART0_BASE +$(call force,CFG_MX8DX,y) +endif + ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxlevk)) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART0_BASE diff --git a/core/arch/arm/plat-imx/imx_pl310.c b/core/arch/arm/plat-imx/imx_pl310.c index 202d64b3ec274623130f2469e5c71991f5e4c489..ddf355e4c9bde09e8899504c72e684cc19946569 100644 --- a/core/arch/arm/plat-imx/imx_pl310.c +++ b/core/arch/arm/plat-imx/imx_pl310.c @@ -23,6 +23,7 @@ #define PL310_PREFETCH_DOUBLE_LINEFILL BIT(30) register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); void arm_cl2_config(vaddr_t pl310_base) { @@ -83,6 +84,11 @@ vaddr_t pl310_base(void) return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1); } +vaddr_t pl310_nsbase(void) +{ + return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 1); +} + #ifdef CFG_PL310_SIP_PROTOCOL uint32_t pl310_enable(void) { diff --git a/core/arch/arm/plat-imx/main.c b/core/arch/arm/plat-imx/main.c index 1a7087dd67711cc35e42dd12de4dbecc8cff5136..9ae1c7ce53181f7f2e0ed2ebecba079f95b04ea4 100644 --- a/core/arch/arm/plat-imx/main.c +++ b/core/arch/arm/plat-imx/main.c @@ -117,6 +117,6 @@ void boot_primary_init_intc(void) #if CFG_TEE_CORE_NB_CORE > 1 void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } #endif diff --git a/core/arch/arm/plat-k3/drivers/sa2ul_rng.c b/core/arch/arm/plat-k3/drivers/sa2ul_rng.c index 1684bff501a272fb36fc0d429ca4e9fea753ba1a..bbbaeacdf519dd8a477979a41d37bc3e60e28ffc 100644 --- a/core/arch/arm/plat-k3/drivers/sa2ul_rng.c +++ b/core/arch/arm/plat-k3/drivers/sa2ul_rng.c @@ -61,12 +61,38 @@ register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); -static unsigned int rng_lock = SPINLOCK_UNLOCK; +static struct mutex fifo_lock = MUTEX_INITIALIZER; static vaddr_t rng; +static bool sa2ul_rng_is_enabled(void) +{ + return io_read32(rng + RNG_CONTROL) & ENABLE_TRNG; +} + +static void sa2ul_rng_init_seq(void) +{ + uint32_t val = 0; + + /* Ensure initial latency */ + val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; + val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; + io_write32(rng + RNG_CONFIG, val); + + /* Configure the desired FROs */ + io_write32(rng + RNG_FRODETUNE, 0x0); + + /* Enable all FROs */ + io_write32(rng + RNG_FROENABLE, 0xffffff); + + io_write32(rng + RNG_CONTROL, ENABLE_TRNG); +} + static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1, uint32_t *word2, uint32_t *word3) { + if (!sa2ul_rng_is_enabled()) + sa2ul_rng_init_seq(); + /* Is the result ready (available)? */ while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) { /* Is the shutdown threshold reached? */ @@ -107,7 +133,7 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) size_t buffer_pos = 0; while (buffer_pos < len) { - uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock); + mutex_lock(&fifo_lock); /* Refill our FIFO */ if (fifo_pos == 0) @@ -117,7 +143,7 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) buffer[buffer_pos++] = fifo.byte[fifo_pos++]; fifo_pos %= 16; - cpu_spin_unlock_xrestore(&rng_lock, exceptions); + mutex_unlock(&fifo_lock); } return TEE_SUCCESS; @@ -125,22 +151,9 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) TEE_Result sa2ul_rng_init(void) { - uint32_t val = 0; - rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); - /* Ensure initial latency */ - val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; - val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; - io_write32(rng + RNG_CONFIG, val); - - /* Configure the desired FROs */ - io_write32(rng + RNG_FRODETUNE, 0x0); - - /* Enable all FROs */ - io_write32(rng + RNG_FROENABLE, 0xffffff); - - io_write32(rng + RNG_CONTROL, ENABLE_TRNG); + sa2ul_rng_init_seq(); IMSG("SA2UL TRNG initialized"); diff --git a/core/arch/arm/plat-k3/main.c b/core/arch/arm/plat-k3/main.c index 531da533e4a172b5034d7262ae9dd1d574da72ab..e029554412f422a166c809b9f725a8c03b51e487 100644 --- a/core/arch/arm/plat-k3/main.c +++ b/core/arch/arm/plat-k3/main.c @@ -39,7 +39,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } void console_init(void) diff --git a/core/arch/arm/plat-ls/main.c b/core/arch/arm/plat-ls/main.c index 3aa97ba9fb59d52fec9b92cb6b84e11fbd43c1f3..8358bc133649722efc0503d4ed2103617a7b2dc1 100644 --- a/core/arch/arm/plat-ls/main.c +++ b/core/arch/arm/plat-ls/main.c @@ -215,9 +215,7 @@ void boot_primary_init_intc(void) gic_init(gic_base + gicc_offset, gic_base + gicd_offset); } -#if !defined(CFG_WITH_ARM_TRUSTED_FW) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } -#endif diff --git a/core/arch/arm/plat-mediatek/main.c b/core/arch/arm/plat-mediatek/main.c index 2470def4183300e7d54b26fd4d2da57e6b247458..de7e06344fbef635e0659c5952f5f64d8b83dbb1 100644 --- a/core/arch/arm/plat-mediatek/main.c +++ b/core/arch/arm/plat-mediatek/main.c @@ -12,8 +12,10 @@ #include <platform_config.h> #include <stdint.h> +#if (CFG_TEE_CORE_LOG_LEVEL != 0) register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); +#endif static struct serial8250_uart_data console_data; @@ -33,7 +35,9 @@ void boot_primary_init_intc(void) void console_init(void) { - serial8250_uart_init(&console_data, CONSOLE_UART_BASE, - CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); - register_serial_console(&console_data.chip); + if (CFG_TEE_CORE_LOG_LEVEL != 0) { + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); + } } diff --git a/core/arch/arm/plat-nuvoton/main.c b/core/arch/arm/plat-nuvoton/main.c index 933fb2dd1a5af0be1865230b33bbbb060b784475..88db73db1d49f314cf5602e4eca92fed1535c2d6 100644 --- a/core/arch/arm/plat-nuvoton/main.c +++ b/core/arch/arm/plat-nuvoton/main.c @@ -26,8 +26,8 @@ #define COLOR_WHITE "\x1B[37m" #define NPCM_MEASURE_BASE 0xF0848000 -#define NPCM_MEASURE_DME 0x0E0 -#define NPCM_MEASURE_SIZE 64 +#define NPCM_MEASURE_UUID 0xC50 +#define NPCM_MEASURE_SIZE 5 static struct ns16550_data console_data __nex_bss; @@ -76,7 +76,7 @@ TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) if (npcm_hwkey.ready) goto out; - vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_DME, + vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_UUID, MEM_AREA_RAM_NSEC, NPCM_MEASURE_SIZE); if (!vaddr) { EMSG("Not enough memory mapped"); diff --git a/core/arch/arm/plat-rcar/conf.mk b/core/arch/arm/plat-rcar/conf.mk index 0de4143dfeda44ccf1a7b154d93fb6c25c107af3..c810dfeb8385025a0f24eea44370bd1282d3e81f 100644 --- a/core/arch/arm/plat-rcar/conf.mk +++ b/core/arch/arm/plat-rcar/conf.mk @@ -24,12 +24,15 @@ CFG_TEE_RAM_VA_SIZE ?= 0x100000 supported-ta-targets = ta_arm64 ifeq ($(CFG_RCAR_GEN3), y) +CFG_DT ?= y +ifeq ($(CFG_RCAR_GEN3_HWRNG), y) +$(warning "Warning: Use of HWRNG can cause crashes on some Renesas SoCs") CFG_WITH_SOFTWARE_PRNG ?= n CFG_HWRNG_QUALITY ?= 1024 CFG_HWRNG_PTA ?= y -CFG_DT ?= y $(call force,CFG_RCAR_ROMAPI, y) endif +endif ifeq ($(CFG_RCAR_GEN4), y) # 1xx - for SCIFxx diff --git a/core/arch/arm/plat-rcar/main.c b/core/arch/arm/plat-rcar/main.c index 9b443f9abae2c1b0495edab23443499fe4f884e3..452e05e97091217977934ea1afb660a7706f0257 100644 --- a/core/arch/arm/plat-rcar/main.c +++ b/core/arch/arm/plat-rcar/main.c @@ -94,5 +94,5 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } diff --git a/core/arch/arm/plat-rcar/romapi.c b/core/arch/arm/plat-rcar/romapi.c index ad0a0d95dc336b6536ae42d65d3e6c4b6401b2cc..19c2045f729e45bfdbb143a59a386a1ecdb7acd3 100644 --- a/core/arch/arm/plat-rcar/romapi.c +++ b/core/arch/arm/plat-rcar/romapi.c @@ -121,6 +121,7 @@ uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], uint8_t *scratch, uint32_t scratch_sz) { uint32_t ret = -1; + int try = 0; paddr_t func_addr = romapi_getrndvector[get_api_table_index()]; paddr_t rndbuff_pa = va2pa(rndbuff); paddr_t scratch_pa = va2pa(scratch); @@ -129,7 +130,13 @@ uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0); assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0); - ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, scratch_sz); + while (try++ < 3) { + ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, + scratch_sz); + if (ret == 0) + break; + IMSG("ROM_GetRndVector() returned "PRIx32, ret); + } /* * ROM code is called with MMU turned off, so any accesses to rndbuff diff --git a/core/arch/arm/plat-rockchip/main.c b/core/arch/arm/plat-rockchip/main.c index b7501ddd6b36d83775dac39869e214b641222a61..a85900fa31434c7a39f93878b62e7aee9d6e5c93 100644 --- a/core/arch/arm/plat-rockchip/main.c +++ b/core/arch/arm/plat-rockchip/main.c @@ -29,7 +29,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } void console_init(void) diff --git a/core/arch/arm/plat-rockchip/platform.c b/core/arch/arm/plat-rockchip/platform.c index 96c343f02dfe14550af0cb5e42e9877509c56418..8028f2c13d1fbae88d2dceac9f0af31c61bd8648 100644 --- a/core/arch/arm/plat-rockchip/platform.c +++ b/core/arch/arm/plat-rockchip/platform.c @@ -19,7 +19,7 @@ int __weak platform_secure_ddr_region(int rgn __maybe_unused, paddr_t st __maybe_unused, size_t sz __maybe_unused) { - MSG("Not protecting region %d: 0x%lx-0x%lx\n", rgn, st, st + sz); + MSG("Not protecting region %d: 0x%lx-0x%lx", rgn, st, st + sz); return 0; } diff --git a/core/arch/arm/plat-rockchip/platform_px30.c b/core/arch/arm/plat-rockchip/platform_px30.c index 8327ca929e27715bdf5a570859de233d74f63191..08cd4906243f81311a7a0c68c12e551c8a7b4554 100644 --- a/core/arch/arm/plat-rockchip/platform_px30.c +++ b/core/arch/arm/plat-rockchip/platform_px30.c @@ -38,7 +38,7 @@ int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) assert(st % SIZE_M(1) == 0); assert(ed % SIZE_M(1) == 0); - DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed); + DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed); /* Map top and base */ io_write32(fw_base + FIREWALL_DDR_FW_DDR_RGN(rgn), diff --git a/core/arch/arm/plat-rockchip/platform_rk3399.c b/core/arch/arm/plat-rockchip/platform_rk3399.c index 053f566e65295ce0288f63b3cf33b6b67e2c5b65..1ff72cee1c4c5eb984ad4760008dd5ae33dbe2cf 100644 --- a/core/arch/arm/plat-rockchip/platform_rk3399.c +++ b/core/arch/arm/plat-rockchip/platform_rk3399.c @@ -32,7 +32,7 @@ int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) assert(st % SIZE_M(1) == 0); assert(ed % SIZE_M(1) == 0); - DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed); + DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed); /* Set ddr region addr start */ io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn), diff --git a/core/arch/arm/plat-rzn1/main.c b/core/arch/arm/plat-rzn1/main.c index ac6d88f8edb23b663a0676a04fa6061cf27083d8..bed02b80f74bad1714683622cf01482922439b50 100644 --- a/core/arch/arm/plat-rzn1/main.c +++ b/core/arch/arm/plat-rzn1/main.c @@ -47,7 +47,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } static TEE_Result rzn1_tz_init(void) diff --git a/core/arch/arm/plat-sam/conf.mk b/core/arch/arm/plat-sam/conf.mk index d546cbc6af70c1ee5f6db3e61c8d4a76ac383926..feef98c0ee5da03a4b976e8f90b6523ab3200493 100644 --- a/core/arch/arm/plat-sam/conf.mk +++ b/core/arch/arm/plat-sam/conf.mk @@ -39,6 +39,9 @@ $(call force,CFG_CORE_HAS_GENERIC_TIMER,n) $(call force,CFG_TZDRAM_START,0x20000000) $(call force,CFG_TZDRAM_SIZE,0x800000) +# This value is forced because this feature isn't used by SAM platforms. +$(call force,CFG_EXTERNAL_DT,n) + CFG_MMAP_REGIONS ?= 24 CFG_SHMEM_START ?= 0x21000000 @@ -108,3 +111,6 @@ $(call force,CFG_SCMI_MSG_CLOCK,y) $(call force,CFG_SCMI_MSG_USE_CLK,y) $(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y) endif + +CFG_DRIVERS_NVMEM ?= y +CFG_ATMEL_SFC ?= y diff --git a/core/arch/arm/plat-sam/main.c b/core/arch/arm/plat-sam/main.c index 503ab0dbd5706a03f45e8787e2256667cc6edbee..1fffce5884fbbb2d826ca99dcf49224650131faf 100644 --- a/core/arch/arm/plat-sam/main.c +++ b/core/arch/arm/plat-sam/main.c @@ -44,6 +44,457 @@ #include <sm/optee_smc.h> #include <tz_matrix.h> +#define MATRIX_AXIMX 1 +#define MATRIX_H64MX 2 +#define MATRIX_H32MX 3 + +static struct matrix matrixes[] = { + { + .matrix = MATRIX_H64MX, + .p = { .pa = AT91C_BASE_MATRIX64 } + }, + { + .matrix = MATRIX_H32MX, + .p = { .pa = AT91C_BASE_MATRIX32, } + } +}; + +static struct peri_security peri_security_array[] = { + { + .peri_id = AT91C_ID_PMC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PMC, + }, + { + .peri_id = AT91C_ID_ARM, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PITC, + }, + { + .peri_id = AT91C_ID_WDT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_WDT, + }, + { + .peri_id = AT91C_ID_GMAC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_GMAC, + }, + { + .peri_id = AT91C_ID_XDMAC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_XDMAC0, + }, + { + .peri_id = AT91C_ID_XDMAC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_XDMAC1, + }, + { + .peri_id = AT91C_ID_ICM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ICM, + }, + { + .peri_id = AT91C_ID_AES, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_AES, + }, + { + .peri_id = AT91C_ID_AESB, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_AESB, + }, + { + .peri_id = AT91C_ID_TDES, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TDES, + }, + { + .peri_id = AT91C_ID_SHA, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SHA, + }, + { + .peri_id = AT91C_ID_MPDDRC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_MPDDRC, + }, + { + .peri_id = AT91C_ID_MATRIX1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_MATRIX32, + }, + { + .peri_id = AT91C_ID_MATRIX0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_MATRIX64, + }, + { + .peri_id = AT91C_ID_SECUMOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SECUMOD, + }, + { + .peri_id = AT91C_ID_HSMC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_HSMC, + }, + { + .peri_id = AT91C_ID_PIOA, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOA, + }, + { + .peri_id = AT91C_ID_FLEXCOM0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM0, + }, + { + .peri_id = AT91C_ID_FLEXCOM1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM1, + }, + { + .peri_id = AT91C_ID_FLEXCOM2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM2, + }, + { + .peri_id = AT91C_ID_FLEXCOM3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM3, + }, + { + .peri_id = AT91C_ID_FLEXCOM4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM4, + }, + { + .peri_id = AT91C_ID_UART0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART0, + }, + { + .peri_id = AT91C_ID_UART1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART1, + }, + { + .peri_id = AT91C_ID_UART2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART2, + }, + { + .peri_id = AT91C_ID_UART3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART3, + }, + { + .peri_id = AT91C_ID_UART4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART4, + }, + { + .peri_id = AT91C_ID_TWI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TWI0, + }, + { + .peri_id = AT91C_ID_TWI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TWI1, + }, + { + .peri_id = AT91C_ID_SDMMC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SDHC0, + }, + { + .peri_id = AT91C_ID_SDMMC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SDHC1, + }, + { + .peri_id = AT91C_ID_SPI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SPI0, + }, + { + .peri_id = AT91C_ID_SPI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SPI1, + }, + { + .peri_id = AT91C_ID_TC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TC0, + }, + { + .peri_id = AT91C_ID_TC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TC1, + }, + { + .peri_id = AT91C_ID_PWM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PWMC, + }, + { + .peri_id = AT91C_ID_ADC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ADC, + }, + { + .peri_id = AT91C_ID_UHPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UDPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UDPHS, + }, + { + .peri_id = AT91C_ID_SSC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SSC0, + }, + { + .peri_id = AT91C_ID_SSC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SSC1, + }, + { + .peri_id = AT91C_ID_LCDC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_LCDC, + }, + { + .peri_id = AT91C_ID_ISI, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_HXISI, + }, + { + .peri_id = AT91C_ID_TRNG, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TRNG, + }, + { + .peri_id = AT91C_ID_PDMIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PDMIC, + }, + { + .peri_id = AT91C_ID_IRQ, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + }, + { + .peri_id = AT91C_ID_SFC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFC, + }, + { + .peri_id = AT91C_ID_SECURAM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SECURAM, + }, + { + .peri_id = AT91C_ID_QSPI0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_QSPI0, + }, + { + .peri_id = AT91C_ID_QSPI1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_QSPI1, + }, + { + .peri_id = AT91C_ID_I2SC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_I2SC0, + }, + { + .peri_id = AT91C_ID_I2SC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_I2SC1, + }, + { + .peri_id = AT91C_ID_CAN0_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CLASSD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_CLASSD, + }, + { + .peri_id = AT91C_ID_SFR, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFR, + }, + { + .peri_id = AT91C_ID_SAIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SAIC, + }, + { + .peri_id = AT91C_ID_AIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + .addr = AT91C_BASE_AIC, + }, + { + .peri_id = AT91C_ID_L2CC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_L2CC, + }, + { + .peri_id = AT91C_ID_CAN0_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIOB, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOB, + }, + { + .peri_id = AT91C_ID_PIOC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOC, + }, + { + .peri_id = AT91C_ID_PIOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOD, + }, + { + .peri_id = AT91C_ID_SDMMC0_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SDMMC1_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SYS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SYSC, + }, + { + .peri_id = AT91C_ID_ACC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ACC, + }, + { + .peri_id = AT91C_ID_RXLP, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_RXLP, + }, + { + .peri_id = AT91C_ID_SFRBU, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFRBU, + }, + { + .peri_id = AT91C_ID_CHIPID, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_CHIPID, + }, +}; + static struct atmel_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); @@ -59,30 +510,24 @@ register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX32, register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX64, CORE_MMU_PGDIR_SIZE); -vaddr_t matrix32_base(void) +struct peri_security *peri_security_get(unsigned int idx) { - static void *va; + struct peri_security *p = NULL; - if (cpu_mmu_enabled()) { - if (!va) - va = phys_to_virt(AT91C_BASE_MATRIX32, MEM_AREA_IO_SEC, - 1); - return (vaddr_t)va; - } - return AT91C_BASE_MATRIX32; + if (idx < ARRAY_SIZE(peri_security_array)) + p = &peri_security_array[idx]; + + return p; } -vaddr_t matrix64_base(void) +struct matrix *matrix_get(unsigned int idx) { - static void *va; + struct matrix *pmatrix = NULL; - if (cpu_mmu_enabled()) { - if (!va) - va = phys_to_virt(AT91C_BASE_MATRIX64, MEM_AREA_IO_SEC, - 1); - return (vaddr_t)va; - } - return AT91C_BASE_MATRIX64; + if (idx < ARRAY_SIZE(matrixes)) + pmatrix = &matrixes[idx]; + + return pmatrix; } static void matrix_configure_slave_h64mx(void) @@ -108,7 +553,7 @@ static void matrix_configure_slave_h64mx(void) | MATRIX_RDNSECH_NS(2) | MATRIX_WRNSECH_NS(1) | MATRIX_WRNSECH_NS(2)); - matrix_configure_slave_security(matrix64_base(), + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_PERI_BRIDGE, srtop_setting, sasplit_setting, @@ -142,11 +587,11 @@ static void matrix_configure_slave_h64mx(void) | MATRIX_WRNSECH_NS(3)); /* DDR port 0 not used from NWd */ for (ddr_port = 1; ddr_port < 8; ddr_port++) { - matrix_configure_slave_security(matrix64_base(), - (H64MX_SLAVE_DDR2_PORT_0 + ddr_port), - srtop_setting, - sasplit_setting, - ssr_setting); + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), + H64MX_SLAVE_DDR2_PORT_0 + + ddr_port, srtop_setting, + sasplit_setting, + ssr_setting); } /* @@ -158,7 +603,7 @@ static void matrix_configure_slave_h64mx(void) sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SRTOP_VALUE_64K); ssr_setting = (MATRIX_LANSECH_S(0) | MATRIX_RDNSECH_S(0) | MATRIX_WRNSECH_S(0)); - matrix_configure_slave_security(matrix64_base(), + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_INTERNAL_SRAM, srtop_setting, sasplit_setting, ssr_setting); @@ -172,10 +617,12 @@ static void matrix_configure_slave_h64mx(void) ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) | MATRIX_WRNSECH_NS(0); - matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI0, + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), + H64MX_SLAVE_QSPI0, srtop_setting, sasplit_setting, ssr_setting); - matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI1, + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), + H64MX_SLAVE_QSPI1, srtop_setting, sasplit_setting, ssr_setting); /* 14: AESB: Default */ @@ -210,7 +657,7 @@ static void matrix_configure_slave_h32mx(void) ssr_setting |= (MATRIX_LANSECH_NS(7) | MATRIX_RDNSECH_NS(7) | MATRIX_WRNSECH_NS(7)); - matrix_configure_slave_security(matrix32_base(), + matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_EXTERNAL_EBI, srtop_setting, sasplit_setting, @@ -222,7 +669,7 @@ static void matrix_configure_slave_h32mx(void) ssr_setting = (MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) | MATRIX_WRNSECH_NS(0)); - matrix_configure_slave_security(matrix32_base(), + matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_NFC_SRAM, srtop_setting, sasplit_setting, @@ -248,7 +695,7 @@ static void matrix_configure_slave_h32mx(void) | MATRIX_WRNSECH_NS(0) | MATRIX_WRNSECH_NS(1) | MATRIX_WRNSECH_NS(2)); - matrix_configure_slave_security(matrix32_base(), + matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_USB, srtop_setting, sasplit_setting, @@ -323,8 +770,8 @@ static unsigned int security_ps_peri_id[] = { static int matrix_init(void) { - matrix_write_protect_disable(matrix64_base()); - matrix_write_protect_disable(matrix32_base()); + matrix_write_protect_disable(matrix_base(MATRIX_H64MX)); + matrix_write_protect_disable(matrix_base(MATRIX_H32MX)); matrix_configure_slave_h64mx(); matrix_configure_slave_h32mx(); diff --git a/core/arch/arm/plat-sam/matrix.c b/core/arch/arm/plat-sam/matrix.c index c0a39e57b1d3e5464ec9fcc4af8771d9477212c4..f897e069523feeab507b8426ecb6f9acef04bf2f 100644 --- a/core/arch/arm/plat-sam/matrix.c +++ b/core/arch/arm/plat-sam/matrix.c @@ -32,469 +32,16 @@ #include <kernel/pm.h> #include <kernel/panic.h> #include <matrix.h> +#include <mm/core_memprot.h> +#include <mm/core_mmu.h> #include <platform_config.h> -#include <sama5d2.h> #include <stdint.h> #include <tz_matrix.h> #include <trace.h> -#define MATRIX_AXIMX 1 -#define MATRIX_H64MX 2 -#define MATRIX_H32MX 3 - -#define SECURITY_TYPE_AS 1 -#define SECURITY_TYPE_NS 2 -#define SECURITY_TYPE_PS 3 - #define WORLD_NON_SECURE 0 #define WORLD_SECURE 1 -#define MATRIX_SPSELR_COUNT 3 -#define MATRIX_SLAVE_COUNT 15 - -struct peri_security { - unsigned int peri_id; - unsigned int matrix; - unsigned int security_type; - paddr_t addr; -}; - -static const struct peri_security peri_security_array[] = { - { - .peri_id = AT91C_ID_PMC, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_PMC, - }, - { - .peri_id = AT91C_ID_ARM, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_PIT, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_PITC, - }, - { - .peri_id = AT91C_ID_WDT, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_WDT, - }, - { - .peri_id = AT91C_ID_GMAC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_GMAC, - }, - { - .peri_id = AT91C_ID_XDMAC0, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_XDMAC0, - }, - { - .peri_id = AT91C_ID_XDMAC1, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_XDMAC1, - }, - { - .peri_id = AT91C_ID_ICM, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_ICM, - }, - { - .peri_id = AT91C_ID_AES, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_AES, - }, - { - .peri_id = AT91C_ID_AESB, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_AESB, - }, - { - .peri_id = AT91C_ID_TDES, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TDES, - }, - { - .peri_id = AT91C_ID_SHA, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SHA, - }, - { - .peri_id = AT91C_ID_MPDDRC, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_MPDDRC, - }, - { - .peri_id = AT91C_ID_MATRIX1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_MATRIX32, - }, - { - .peri_id = AT91C_ID_MATRIX0, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_MATRIX64, - }, - { - .peri_id = AT91C_ID_SECUMOD, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_SECUMOD, - }, - { - .peri_id = AT91C_ID_HSMC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_HSMC, - }, - { - .peri_id = AT91C_ID_PIOA, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_PIOA, - }, - { - .peri_id = AT91C_ID_FLEXCOM0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_FLEXCOM0, - }, - { - .peri_id = AT91C_ID_FLEXCOM1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_FLEXCOM1, - }, - { - .peri_id = AT91C_ID_FLEXCOM2, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_FLEXCOM2, - }, - { - .peri_id = AT91C_ID_FLEXCOM3, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_FLEXCOM3, - }, - { - .peri_id = AT91C_ID_FLEXCOM4, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_FLEXCOM4, - }, - { - .peri_id = AT91C_ID_UART0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UART0, - }, - { - .peri_id = AT91C_ID_UART1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UART1, - }, - { - .peri_id = AT91C_ID_UART2, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UART2, - }, - { - .peri_id = AT91C_ID_UART3, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UART3, - }, - { - .peri_id = AT91C_ID_UART4, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UART4, - }, - { - .peri_id = AT91C_ID_TWI0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TWI0, - }, - { - .peri_id = AT91C_ID_TWI1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TWI1, - }, - { - .peri_id = AT91C_ID_SDMMC0, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SDHC0, - }, - { - .peri_id = AT91C_ID_SDMMC1, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SDHC1, - }, - { - .peri_id = AT91C_ID_SPI0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SPI0, - }, - { - .peri_id = AT91C_ID_SPI1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SPI1, - }, - { - .peri_id = AT91C_ID_TC0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TC0, - }, - { - .peri_id = AT91C_ID_TC1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TC1, - }, - { - .peri_id = AT91C_ID_PWM, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_PWMC, - }, - { - .peri_id = AT91C_ID_ADC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_ADC, - }, - { - .peri_id = AT91C_ID_UHPHS, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_UDPHS, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_UDPHS, - }, - { - .peri_id = AT91C_ID_SSC0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SSC0, - }, - { - .peri_id = AT91C_ID_SSC1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SSC1, - }, - { - .peri_id = AT91C_ID_LCDC, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_LCDC, - }, - { - .peri_id = AT91C_ID_ISI, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_HXISI, - }, - { - .peri_id = AT91C_ID_TRNG, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_TRNG, - }, - { - .peri_id = AT91C_ID_PDMIC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_PDMIC, - }, - { - .peri_id = AT91C_ID_IRQ, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_NS, - }, - { - .peri_id = AT91C_ID_SFC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SFC, - }, - { - .peri_id = AT91C_ID_SECURAM, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_SECURAM, - }, - { - .peri_id = AT91C_ID_QSPI0, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_QSPI0, - }, - { - .peri_id = AT91C_ID_QSPI1, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_QSPI1, - }, - { - .peri_id = AT91C_ID_I2SC0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_I2SC0, - }, - { - .peri_id = AT91C_ID_I2SC1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_I2SC1, - }, - { - .peri_id = AT91C_ID_CAN0_INT0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_CAN1_INT0, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_CLASSD, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_CLASSD, - }, - { - .peri_id = AT91C_ID_SFR, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SFR, - }, - { - .peri_id = AT91C_ID_SAIC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_SAIC, - }, - { - .peri_id = AT91C_ID_AIC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_NS, - .addr = AT91C_BASE_AIC, - }, - { - .peri_id = AT91C_ID_L2CC, - .matrix = MATRIX_H64MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_L2CC, - }, - { - .peri_id = AT91C_ID_CAN0_INT1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_CAN1_INT1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_GMAC_Q1, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_GMAC_Q2, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_PIOB, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_PIOB, - }, - { - .peri_id = AT91C_ID_PIOC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_PIOC, - }, - { - .peri_id = AT91C_ID_PIOD, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_AS, - .addr = AT91C_BASE_PIOD, - }, - { - .peri_id = AT91C_ID_SDMMC0_TIMER, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_SDMMC1_TIMER, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - }, - { - .peri_id = AT91C_ID_SYS, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SYSC, - }, - { - .peri_id = AT91C_ID_ACC, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_ACC, - }, - { - .peri_id = AT91C_ID_RXLP, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_RXLP, - }, - { - .peri_id = AT91C_ID_SFRBU, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_SFRBU, - }, - { - .peri_id = AT91C_ID_CHIPID, - .matrix = MATRIX_H32MX, - .security_type = SECURITY_TYPE_PS, - .addr = AT91C_BASE_CHIPID, - }, -}; - static void matrix_write(unsigned int base, unsigned int offset, const unsigned int value) @@ -507,10 +54,24 @@ static unsigned int matrix_read(int base, unsigned int offset) return io_read32(offset + base); } +vaddr_t matrix_base(unsigned int matrix) +{ + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + do { + pmatrix = matrix_get(i++); + if (!pmatrix) + panic("Invalid matrix"); + } while (pmatrix->matrix != matrix); + + return io_pa_or_va_secure(&pmatrix->p, CORE_MMU_PGDIR_SIZE); +} + void matrix_write_protect_enable(unsigned int matrix_base) { matrix_write(matrix_base, MATRIX_WPMR, - (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE)); + MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE); } void matrix_write_protect_disable(unsigned int matrix_base) @@ -531,37 +92,29 @@ void matrix_configure_slave_security(unsigned int matrix_base, static const struct peri_security *get_peri_security(unsigned int peri_id) { - unsigned int i; + unsigned int i = 0; + struct peri_security *p = NULL; - for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) { - if (peri_id == peri_security_array[i].peri_id) - return &peri_security_array[i]; - } + do { + p = peri_security_get(i++); + if (p && peri_id == p->peri_id) + break; + } while (p); - return NULL; + return p; } static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id, unsigned int world) { - unsigned int base; - unsigned int spselr; - unsigned int idx; - unsigned int bit; + unsigned int spselr = 0; + unsigned int idx = peri_id / 32; + unsigned int bit = 0x01 << (peri_id % 32); + unsigned int base = matrix_base(matrix); - idx = peri_id / 32; if (idx > 3) return -1; - bit = (0x01 << (peri_id % 32)); - - if (matrix == MATRIX_H32MX) - base = matrix32_base(); - else if (matrix == MATRIX_H64MX) - base = matrix64_base(); - else - return -1; - spselr = matrix_read(base, MATRIX_SPSELR(idx)); if (world == WORLD_SECURE) spselr &= ~bit; @@ -576,17 +129,19 @@ TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id) { unsigned int i = 0; paddr_t pbase = 0; + struct peri_security *p = NULL; pbase = fdt_reg_base_address(fdt, node); if (pbase == DT_INFO_INVALID_REG) return TEE_ERROR_BAD_PARAMETERS; - for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) { - if (peri_security_array[i].addr == pbase) { - *id = peri_security_array[i].peri_id; + do { + p = peri_security_get(i++); + if (p && p->addr == pbase) { + *id = p->peri_id; return TEE_SUCCESS; } - } + } while (p); return TEE_ERROR_ITEM_NOT_FOUND; } @@ -605,17 +160,16 @@ int matrix_configure_periph_secure(unsigned int peri_id) int matrix_configure_periph_non_secure(unsigned int *peri_id_array, unsigned int size) { - unsigned int i; - unsigned int *peri_id_p; - unsigned int matrix; - unsigned int peri_id; - const struct peri_security *peripheral_sec; - int ret; + unsigned int i = 0; + unsigned int *peri_id_p = peri_id_array; + unsigned int matrix = 0; + unsigned int peri_id = 0; + const struct peri_security *peripheral_sec = NULL; + int ret = 0; if (!peri_id_array || !size) return -1; - peri_id_p = peri_id_array; for (i = 0; i < size; i++) { peripheral_sec = get_peri_security(*peri_id_p); if (!peripheral_sec) @@ -638,17 +192,6 @@ int matrix_configure_periph_non_secure(unsigned int *peri_id_array, } #ifdef CFG_PM_ARM32 -struct matrix_state { - uint32_t spselr[MATRIX_SPSELR_COUNT]; - uint32_t ssr[MATRIX_SLAVE_COUNT]; - uint32_t srtsr[MATRIX_SLAVE_COUNT]; - uint32_t sassr[MATRIX_SLAVE_COUNT]; - uint32_t meier; - uint32_t meimr; -}; - -static struct matrix_state matrix32_state; -static struct matrix_state matrix64_state; static void matrix_save_regs(vaddr_t base, struct matrix_state *state) { @@ -669,8 +212,11 @@ static void matrix_save_regs(vaddr_t base, struct matrix_state *state) static void matrix_suspend(void) { - matrix_save_regs(matrix32_base(), &matrix32_state); - matrix_save_regs(matrix64_base(), &matrix64_state); + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) + matrix_save_regs(matrix_base(pmatrix->matrix), &pmatrix->state); } static void matrix_restore_regs(vaddr_t base, struct matrix_state *state) @@ -694,8 +240,12 @@ static void matrix_restore_regs(vaddr_t base, struct matrix_state *state) static void matrix_resume(void) { - matrix_restore_regs(matrix32_base(), &matrix32_state); - matrix_restore_regs(matrix64_base(), &matrix64_state); + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) + matrix_restore_regs(matrix_base(pmatrix->matrix), + &pmatrix->state); } static TEE_Result matrix_pm(enum pm_op op, uint32_t pm_hint __unused, diff --git a/core/arch/arm/plat-sam/matrix.h b/core/arch/arm/plat-sam/matrix.h index 216905720dcd6156455126e19b698ee53b8174d9..eefe2d1828a7dd1ffdb840b7aaabffa4e5566b70 100644 --- a/core/arch/arm/plat-sam/matrix.h +++ b/core/arch/arm/plat-sam/matrix.h @@ -29,22 +29,58 @@ #ifndef MATRIX_H #define MATRIX_H +#include <mm/core_memprot.h> +#include <stdint.h> #include <tee_api_types.h> -extern void matrix_write_protect_enable(unsigned int matrix_base); -extern void matrix_write_protect_disable(unsigned int matrix_base); -extern void matrix_configure_slave_security(unsigned int matrix_base, - unsigned int slave, - unsigned int srtop_setting, - unsigned int srsplit_setting, - unsigned int ssr_setting); +#define SECURITY_TYPE_AS 1 +#define SECURITY_TYPE_NS 2 +#define SECURITY_TYPE_PS 3 + +#define MATRIX_SPSELR_COUNT 3 +#define MATRIX_SLAVE_COUNT 15 + +#ifdef CFG_PM_ARM32 +struct matrix_state { + uint32_t spselr[MATRIX_SPSELR_COUNT]; + uint32_t ssr[MATRIX_SLAVE_COUNT]; + uint32_t srtsr[MATRIX_SLAVE_COUNT]; + uint32_t sassr[MATRIX_SLAVE_COUNT]; + uint32_t meier; + uint32_t meimr; +}; +#endif + +struct matrix { + unsigned int matrix; + struct io_pa_va p; +#ifdef CFG_PM_ARM32 + struct matrix_state state; +#endif +}; + +struct peri_security { + unsigned int peri_id; + unsigned int matrix; + unsigned int security_type; + paddr_t addr; +}; + +struct peri_security *peri_security_get(unsigned int idx); +struct matrix *matrix_get(unsigned int idx); +vaddr_t matrix_base(unsigned int matrix); + +void matrix_write_protect_enable(unsigned int matrix_base); +void matrix_write_protect_disable(unsigned int matrix_base); +void matrix_configure_slave_security(unsigned int matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting); int matrix_configure_periph_non_secure(unsigned int *peri_id_array, unsigned int size); int matrix_configure_periph_secure(unsigned int peri_id); TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id); -vaddr_t matrix32_base(void); -vaddr_t matrix64_base(void); - #endif /* #ifndef MATRIX_H */ diff --git a/core/arch/arm/plat-sam/platform_config.h b/core/arch/arm/plat-sam/platform_config.h index 9742c6115653b4968ea191fb1e77b94a3ca995c1..d7f1f5bda811954521a28a5d91ffa95b5bd6578f 100644 --- a/core/arch/arm/plat-sam/platform_config.h +++ b/core/arch/arm/plat-sam/platform_config.h @@ -30,7 +30,11 @@ #define PLATFORM_CONFIG_H #include <mm/generic_ram_layout.h> +#if defined(PLATFORM_FLAVOR_sama7g54_ek) +#include <sama7g5.h> +#else #include <sama5d2.h> +#endif #define STACK_ALIGNMENT 64 @@ -41,6 +45,23 @@ #error "LPAE not supported" #endif +#if defined(PLATFORM_FLAVOR_sama7g54_ek) +#define CONSOLE_UART_BASE (FLEXCOM3_BASE_ADDRESS + 0x200) +#define SFR_BASE SFR_BASE_ADDRESS +#define AT91C_BASE_TC0 TC0_BASE_ADDRESS +#define AT91C_ID_TC0 ID_TC0_CHANNEL0 +#define AT91C_ID_TC1 ID_TC1_CHANNEL0 +#define AT91C_ID_SYS ID_RSTC +#define AT91C_ID_PIOA ID_PIOA +#define AT91C_ID_PIOB ID_PIOB +#define AT91C_ID_PIOC ID_PIOC +#define AT91C_ID_PIOD ID_PIOD +#define AT91C_ID_WDT ID_DWDT_SW +#define AT91C_ID_TRNG ID_TRNG +#define AT91C_ID_SECUMOD ID_SECUMOD +#define AT91C_ID_SFR ID_SFR +#define AT91C_ID_SFRBU ID_SFRBU +#else #if defined(PLATFORM_FLAVOR_sama5d27_wlsom1_ek) #define CONSOLE_UART_BASE AT91C_BASE_UART0 #else @@ -49,6 +70,7 @@ #define PL310_BASE (AT91C_BASE_L2CC) #define SFR_BASE (AT91C_BASE_SFR) +#endif /* * PL310 Auxiliary Control Register diff --git a/core/arch/arm/plat-sam/sama7g5.h b/core/arch/arm/plat-sam/sama7g5.h new file mode 100644 index 0000000000000000000000000000000000000000..46f6bd28b631b0299f9dff7568738f2049d428bd --- /dev/null +++ b/core/arch/arm/plat-sam/sama7g5.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Header file for ATSAMA7G54 + * + * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries. + */ + +#ifndef _SAMA7G54_H_ +#define _SAMA7G54_H_ + +/* + * SAMA7G54 definitions + * This file defines all structures and symbols for SAMA7G54: + * - registers and bitfields + * - peripheral base address + * - peripheral ID + * - PIO definitions + */ + +#define GIC_DISTRIBUTOR_BASE 0xE8C11000 /* Base for GIC distributor interface */ +#define GIC_INTERFACE_BASE 0xE8C12000 /* Base address for GIC CPU interface */ +#define GICC_SIZE 0x1000 +#define GICD_SIZE 0x1000 + +/* ************************************************************************** */ +/* PERIPHERAL ID DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define ID_DWDT_SW 0 /* Dual Watchdog Timer, Secure World (DWDT_SW) */ +#define ID_DWDT_NSW 1 /* DWDT Non Secure World, interrupt (DWDT_NSW) */ +#define ID_DWDT_NSW_ALARM 2 /* DWDT Non Secure World Alarm, interrupt */ +#define ID_SCKC 4 /* Slow Clock Controller (SCKC) */ +#define ID_SHDWC 5 /* SHutDoWn Controller (SHDWC) */ +#define ID_RSTC 6 /* Reset Controller (RSTC) */ +#define ID_RTC 7 /* Real-Time Clock (RTC) */ +#define ID_RTT 8 /* Real-Time Timer (RTT) */ +#define ID_CHIPID 9 /* Chip Identifier (CHIPID) */ +#define ID_PMC 10 /* Power Management Controller (PMC) */ +#define ID_PIOA 11 /* For PIO 0 to 31 (PIOA) */ +#define ID_PIOB 12 /* For PIO 32 to 63, interrupt (PIOB) */ +#define ID_PIOC 13 /* For PIO 64 to 95, interrupt (PIOC) */ +#define ID_PIOD 14 /* For PIO 96 to 127, interrupt (PIOD) */ +#define ID_PIOE 15 /* For PIO 128 to 136, interrupt (PIOE) */ +#define ID_SECUMOD 17 /* Security Module (SECUMOD) */ +#define ID_SECURAM 18 /* Secret RAM (SECURAM) */ +#define ID_SFR 19 /* Special Function Register (SFR) */ +#define ID_SFRBU 20 /* Special Function Register in BackUp zone */ +#define ID_HSMC 21 /* Static Memory Controller - NAND (HSMC) */ +#define ID_XDMAC0 22 /* DMA 0, mem to periph, 32 Channels (XDMAC0) */ +#define ID_XDMAC1 23 /* DMA 1, mem to periph, 32 Channels (XDMAC1) */ +#define ID_XDMAC2 24 /* DMA 2, mem to mem, 4 Channels (XDMAC2) */ +#define ID_ACC 25 /* Analog Comparator Controller (ACC) */ +#define ID_ADC 26 /* Analog-to-Digital Converter (ADC) */ +#define ID_AES 27 /* Advanced Encryption Standard (AES) */ +#define ID_TZAESBASC 28 /* TZ AES Bridge - Address Space Controlller */ +#define ID_ASRC 30 /* Asynchronous Sample Rate Converter (ASRC) */ +#define ID_CPKCC 32 /* Classic Public Key Cryptography Controller */ +#define ID_CSI 33 /* CSI 2 between ISC and MIPI PHY (CSI) */ +#define ID_CSI2DC 34 /* CSI to Demultiplexer Controller (CSI2DC) */ +#define ID_DDRPUBL 35 /* DDR SDRAM PHY Utility Block "Lite" aka PUBL */ +#define ID_DDRUMCTL 36 /* Universal DDR-SDRAM Memory Controller */ +#define ID_EIC 37 /* External Interrupt Controller (EIC) */ +#define ID_FLEXCOM0 38 /* Flexcom 0 (FLEXCOM0) */ +#define ID_FLEXCOM1 39 /* Flexcom 1 (FLEXCOM1) */ +#define ID_FLEXCOM2 40 /* Flexcom 2 (FLEXCOM2) */ +#define ID_FLEXCOM3 41 /* Flexcom 3 (FLEXCOM3) */ +#define ID_FLEXCOM4 42 /* Flexcom 4 (FLEXCOM4) */ +#define ID_FLEXCOM5 43 /* Flexcom 5 (FLEXCOM5) */ +#define ID_FLEXCOM6 44 /* Flexcom 6 (FLEXCOM6) */ +#define ID_FLEXCOM7 45 /* Flexcom 7 (FLEXCOM7) */ +#define ID_FLEXCOM8 46 /* Flexcom 8 (FLEXCOM8) */ +#define ID_FLEXCOM9 47 /* Flexcom 9 (FLEXCOM9) */ +#define ID_FLEXCOM10 48 /* Flexcom 10 (FLEXCOM10) */ +#define ID_FLEXCOM11 49 /* Flexcom 11 (FLEXCOM11) */ +#define ID_GMAC0 51 /* Gigabit Ethernet MAC (GMAC0) */ +#define ID_GMAC1 52 /* Ethernet MAC (GMAC1) */ +#define ID_GMAC0_TSU 53 /* GMAC - TSU Generic Clock - No Interrupt */ +#define ID_GMAC1_TSU 54 /* EMAC - TSU Generic Clock - No Interrupt */ +#define ID_ICM 55 /* Integrity Check Monitor (ICM) */ +#define ID_ISC 56 /* Camera Interface (ISC) */ +#define ID_I2SMCC0 57 /* Inter-IC Sound Controller 0 (I2SMCC0) */ +#define ID_I2SMCC1 58 /* Inter-IC Sound Controller 1 (I2SMCC1) */ +#define ID_MATRIX 60 /* HSS AHB Matrix (MATRIX) */ +#define ID_MCAN0 61 /* Master CAN 0 (MCAN0) */ +#define ID_MCAN1 62 /* Master CAN 1 (MCAN1) */ +#define ID_MCAN2 63 /* Master CAN 2 (MCAN2) */ +#define ID_MCAN3 64 /* Master CAN 3 (MCAN3) */ +#define ID_MCAN4 65 /* Master CAN 4 (MCAN4) */ +#define ID_MCAN5 66 /* Master CAN 5 (MCAN5) */ +#define ID_OTPC 67 /* One Time Programmable memory Controller */ +#define ID_PDMC0 68 /* Pulse Density Modulation Controller 0 */ +#define ID_PDMC1 69 /* Pulse Density Modulation Controller 1 */ +#define ID_PIT64B0 70 /* 64-bit Periodic Interval Timer 0 (PIT64B0) */ +#define ID_PIT64B1 71 /* 64-bit Periodic Interval Timer 1 (PIT64B1) */ +#define ID_PIT64B2 72 /* 64-bit Periodic Interval Timer 2 (PIT64B2) */ +#define ID_PIT64B3 73 /* 64-bit Periodic Interval Timer 3 (PIT64B3) */ +#define ID_PIT64B4 74 /* 64-bit Periodic Interval Timer 4 (PIT64B4) */ +#define ID_PIT64B5 75 /* 64-bit Periodic Interval Timer 5 (PIT64B5) */ +#define ID_PWM 77 /* Pulse Width Modulation (PWM) */ +#define ID_QSPI0 78 /* Quad IO Serial Peripheral Interface 0 */ +#define ID_QSPI1 79 /* Quad IO Serial Peripheral Interface 1 */ +#define ID_SDMMC0 80 /* Ultra HS SD Host controller 0 (eMMC 5.1) */ +#define ID_SDMMC1 81 /* Ultra HS SD Host controller 1 (eMMC 4.51) */ +#define ID_SDMMC2 82 /* Ultra HS SD Host controller 2 (eMMC 4.51) */ +#define ID_SHA 83 /* Secure Hash Algorithm (SHA) */ +#define ID_SPDIFRX 84 /* Sony Philips Digital Interface RX (SPDIFRX) */ +#define ID_SPDIFTX 85 /* Sony Philips Digital Interface TX (SPDIFTX) */ +#define ID_SSC0 86 /* Synchronous Serial Interface 0 (SSC0) */ +#define ID_SSC1 87 /* Synchronous Serial Interface 1 (SSC1) */ +#define ID_TC0_CHANNEL0 88 /* 32-bit Timer Counter 0 Channel 0 */ +#define ID_TC0_CHANNEL1 89 /* 32-bit Timer Counter 0 Channel 1 interrupt */ +#define ID_TC0_CHANNEL2 90 /* 32-bit Timer Counter 0 Channel 2 interrupt */ +#define ID_TC1_CHANNEL0 91 /* 32-bit Timer Counter 1 Channel 0 */ +#define ID_TC1_CHANNEL1 92 /* 32-bit Timer Counter 1 Channel 1 interrupt */ +#define ID_TC1_CHANNEL2 93 /* 32-bit Timer Counter 1 Channel 2 interrupt */ +#define ID_TCPCA 94 /* USB Type-C Port Controller A (TCPCA) */ +#define ID_TCPCB 95 /* USB Type-C Port Controller B (TCPCB) */ +#define ID_TDES 96 /* Triple Data Encryption System (TDES) */ +#define ID_TRNG 97 /* True Random Number Generator (TRNG) */ +#define ID_TZAESB_NS 98 /* TZAESB Non-Secure (Clocks & Interrupt) */ +#define ID_TZAESB_NS_SINT 99 /* TZAESB Non-Secure (Interrupt only) */ +#define ID_TZAESB_S 100 /* TZAESB Secure */ +#define ID_TZAESB_S_SINT 101 /* TZAESB Secure (Interrupt only) */ +#define ID_TZC 102 /* TrustZone Address Space Controller (TZC400) */ +#define ID_TZPM 103 /* TrustZone Peripheral Manager (TZPM) */ +#define ID_UDPHSA 104 /* USB Device High Speed A (UDPHSA) */ +#define ID_UDPHSB 105 /* USB Device High Speed B (UDPHSB) */ +#define ID_UHPHS 106 /* USB Host Controller High Speed (UHPHS) */ +#define ID_XDMAC0_SINT 112 /* DMA 0, mem to periph, 32 CH, Secure INT */ +#define ID_XDMAC1_SINT 113 /* DMA 1, mem to periph, 32 CH, Secure INT */ +#define ID_XDMAC2_SINT 114 /* DMA 2, mem to mem, 4 Channels, Secure INT */ +#define ID_AES_SINT 115 /* Advanced Encryption Standard, Secure INT */ +#define ID_GMAC0_Q1 116 /* GMAC0 Queue 1 */ +#define ID_GMAC0_Q2 117 /* GMAC0 Queue 2 */ +#define ID_GMAC0_Q3 118 /* GMAC0 Queue 3 */ +#define ID_GMAC0_Q4 119 /* GMAC0 Queue 4 */ +#define ID_GMAC0_Q5 120 /* GMAC0 Queue 5 */ +#define ID_GMAC1_Q1 121 /* GMAC1 Queue 1 */ +#define ID_ICM_SINT 122 /* Integrity Check Monitor, Secure INTerrupt */ +#define ID_MCAN0_INT1 123 /* MCAN0 interrupt1 (MCAN0_INT1) */ +#define ID_MCAN1_INT1 124 /* MCAN1 interrupt1 (MCAN1_INT1) */ +#define ID_MCAN2_INT1 125 /* MCAN2 interrupt1 (MCAN2_INT1) */ +#define ID_MCAN3_INT1 126 /* MCAN3 interrupt1 (MCAN3_INT1) */ +#define ID_MCAN4_INT1 127 /* MCAN4 interrupt1 (MCAN4_INT1) */ +#define ID_MCAN5_INT1 128 /* MCAN5 interrupt1 (MCAN5_INT1) */ +#define ID_PIOA_SINT 129 /* For PIO 0 to 31, Secure INTerrupt */ +#define ID_PIOB_SINT 130 /* For PIO 32 to 63, Secure INTerrupt */ +#define ID_PIOC_SINT 131 /* For PIO 64 to 95, Secure INTerrupt */ +#define ID_PIOD_SINT 132 /* For PIO 96 to 127, Secure INTerrupt */ +#define ID_PIOE_SINT 133 /* For PIO 128 to 136, Secure INTerrupt */ +#define ID_PIT64B0_SINT 135 /* 64-bit PIT 0, Secure INTerrupt */ +#define ID_PIT64B1_SINT 136 /* 64-bit PIT 1, Secure INTerrupt */ +#define ID_PIT64B2_SINT 137 /* 64-bit PIT 2, Secure INTerrupt */ +#define ID_PIT64B3_SINT 138 /* 64-bit PIT 3, Secure INTerrupt */ +#define ID_PIT64B4_SINT 139 /* 64-bit PIT 4, Secure INTerrupt */ +#define ID_PIT64B5_SINT 140 /* 64-bit PIT 5, Secure INTerrupt */ +#define ID_SDMMC0_TIMER 141 /* SD Host controller 0 (eMMC 5.1) Timer int */ +#define ID_SDMMC1_TIMER 142 /* SD Host controller 1 (eMMC 4.51) Timer int */ +#define ID_SDMMC2_TIMER 143 /* SD Host controller 2 (eMMC 4.51) Timer int */ +#define ID_SHA_SINT 144 /* Secure Hash Algorithm, Secure INTerrupt */ +#define ID_TC0_SINT0 145 /* 32-bit TC 0 Channel 0, Secure INTerrupt */ +#define ID_TC0_SINT1 146 /* 32-bit TC 0 Channel 1, Secure INTerrupt */ +#define ID_TC0_SINT2 147 /* 32-bit TC 0 Channel 2 (TC0_SINT2) */ +#define ID_TC1_SINT0 148 /* 32-bit TC 1 Channel 0, Secure INTerrupt */ +#define ID_TC1_SINT1 149 /* 32-bit TC 1 Channel 1, Secure INTerrupt */ +#define ID_TC1_SINT2 150 /* 32-bit TC 1 Channel 2, Secure INTerrupt */ +#define ID_TDES_SINT 151 /* Triple Data Encryption System, Secure INT */ +#define ID_TRNG_SINT 152 /* True Random Number Generator, Secure INT */ +#define ID_EXT_IRQ0 153 /* External Interrupt ID0 (FIQ) (EXT_IRQ0) */ +#define ID_EXT_IRQ1 154 /* External Interrupt ID1 (IRQ) (EXT_IRQ1) */ + +#define ID_PERIPH_MAX 154 /* Number of peripheral IDs */ + +/* ************************************************************************** */ +/* BASE ADDRESS DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define ACC_BASE_ADDRESS 0xe1600000 +#define ADC_BASE_ADDRESS 0xe1000000 +#define AES_BASE_ADDRESS 0xe1810000 +#define ASRC_BASE_ADDRESS 0xe1610000 +#define BSC_BASE_ADDRESS 0xe001d054 +#define CHIPID_BASE_ADDRESS 0xe0020000 +#define CSI_BASE_ADDRESS 0xe1400000 +#define CPKCC_BASE_ADDRESS 0xe000c000 +#define CSI2DC_BASE_ADDRESS 0xe1404000 +#define DDRPUBL_BASE_ADDRESS 0xe3804000 +#define DWDT_BASE_ADDRESS 0xe001c000 +#define EIC_BASE_ADDRESS 0xe1628000 +#define FLEXCOM0_BASE_ADDRESS 0xe1818000 +#define FLEXCOM1_BASE_ADDRESS 0xe181c000 +#define FLEXCOM2_BASE_ADDRESS 0xe1820000 +#define FLEXCOM3_BASE_ADDRESS 0xe1824000 +#define FLEXCOM4_BASE_ADDRESS 0xe2018000 +#define FLEXCOM5_BASE_ADDRESS 0xe201c000 +#define FLEXCOM6_BASE_ADDRESS 0xe2020000 +#define FLEXCOM7_BASE_ADDRESS 0xe2024000 +#define FLEXCOM8_BASE_ADDRESS 0xe2818000 +#define FLEXCOM9_BASE_ADDRESS 0xe281c000 +#define FLEXCOM10_BASE_ADDRESS 0xe2820000 +#define FLEXCOM11_BASE_ADDRESS 0xe2824000 +#define GMAC0_BASE_ADDRESS 0xe2800000 +#define GMAC1_BASE_ADDRESS 0xe2804000 +#define GPBR_BASE_ADDRESS 0xe001d060 +#define I2SMCC0_BASE_ADDRESS 0xe161c000 +#define I2SMCC1_BASE_ADDRESS 0xe1620000 +#define ICM_BASE_ADDRESS 0xe081c000 +#define ISC_BASE_ADDRESS 0xe1408000 +#define MATRIX_BASE_ADDRESS 0xe0804000 +#define MCAN0_BASE_ADDRESS 0xe0828000 +#define MCAN1_BASE_ADDRESS 0xe082c000 +#define MCAN2_BASE_ADDRESS 0xe0830000 +#define MCAN3_BASE_ADDRESS 0xe0834000 +#define MCAN4_BASE_ADDRESS 0xe0838000 +#define MCAN5_BASE_ADDRESS 0xe083c000 +#define NICGPV_BASE_ADDRESS 0xe8b00000 +#define OTPC_BASE_ADDRESS 0xe8c00000 +#define PDMC0_BASE_ADDRESS 0xe1608000 +#define PDMC1_BASE_ADDRESS 0xe160c000 +#define PIO_BASE_ADDRESS 0xe0014000 +#define PIT64B0_BASE_ADDRESS 0xe1800000 +#define PIT64B1_BASE_ADDRESS 0xe1804000 +#define PIT64B2_BASE_ADDRESS 0xe1808000 +#define PIT64B3_BASE_ADDRESS 0xe2004000 +#define PIT64B4_BASE_ADDRESS 0xe2008000 +#define PIT64B5_BASE_ADDRESS 0xe2810000 +#define PMC_BASE_ADDRESS 0xe0018000 +#define PWM_BASE_ADDRESS 0xe1604000 +#define QSPI0_BASE_ADDRESS 0xe080c000 +#define QSPI1_BASE_ADDRESS 0xe0810000 +#define RSTC_BASE_ADDRESS 0xe001d000 +#define RTC_BASE_ADDRESS 0xe001d0a8 +#define RTT_BASE_ADDRESS 0xe001d020 +#define SCKC_BASE_ADDRESS 0xe001d050 +#define SDMMC0_BASE_ADDRESS 0xe1204000 +#define SDMMC1_BASE_ADDRESS 0xe1208000 +#define SDMMC2_BASE_ADDRESS 0xe120c000 +#define SECUMOD_BASE_ADDRESS 0xe0004000 +#define SFR_BASE_ADDRESS 0xe1624000 +#define SFRBU_BASE_ADDRESS 0xe0008000 +#define SHA_BASE_ADDRESS 0xe1814000 +#define SHDWC_BASE_ADDRESS 0xe001d010 +#define HSMC_BASE_ADDRESS 0xe0808000 +#define SPDIFRX_BASE_ADDRESS 0xe1614000 +#define SPDIFTX_BASE_ADDRESS 0xe1618000 +#define SSC0_BASE_ADDRESS 0xe180c000 +#define SSC1_BASE_ADDRESS 0xe200c000 +#define SYSCWP_BASE_ADDRESS 0xe001d0dc +#define TC0_BASE_ADDRESS 0xe2814000 +#define TC1_BASE_ADDRESS 0xe0800000 +#define TCPCA_BASE_ADDRESS 0xe0840000 +#define TCPCB_BASE_ADDRESS 0xe0844000 +#define TDES_BASE_ADDRESS 0xe2014000 +#define TRNG_BASE_ADDRESS 0xe2010000 +#define TZAESBNS_BASE_ADDRESS 0xe0820000 +#define TZAESBS_BASE_ADDRESS 0xe0824000 +#define TZAESBASC_BASE_ADDRESS 0xe2000000 +#define TZC_BASE_ADDRESS 0xe3000000 +#define TZPM_BASE_ADDRESS 0xe0010000 +#define DDRUMCTL_BASE_ADDRESS 0xe3800000 +#define UDPHSA_BASE_ADDRESS 0xe0814000 +#define UDPHSB_BASE_ADDRESS 0xe0818000 +#define UHPHS_OHCI_BASE_ADDRESS 0x00400000 +#define UHPHS_EHCI_BASE_ADDRESS 0x00500000 +#define XDMAC0_BASE_ADDRESS 0xe2808000 +#define XDMAC1_BASE_ADDRESS 0xe280c000 +#define XDMAC2_BASE_ADDRESS 0xe1200000 + +/* ************************************************************************** */ +/* MEMORY MAPPING DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define IROM_SIZE 0x00014000 +#define ECC_ROM_SIZE 0x00018000 +#define CPKCC_ROM_SIZE 0x00010000 +#define CPKCC_RAM_SIZE 0x00001000 +#define IRAM_SIZE 0x00020000 +#define UDPHS_RAMA_SIZE 0x00100000 +#define UDPHS_RAMB_SIZE 0x00100000 +#define UHPHS_OHCI_SIZE 0x00001000 +#define UHPHS_EHCI_SIZE 0x00100000 +#define NFC_RAM_SIZE 0x00003000 +#define NFC_SIZE 0x08000000 +#define QSPIMEM0_SIZE 0x10000000 +#define QSPIMEM1_SIZE 0x10000000 +#define EBI_CS0_SIZE 0x08000000 +#define EBI_CS1_SIZE 0x08000000 +#define EBI_CS2_SIZE 0x08000000 +#define EBI_CS3_SIZE 0x08000000 +#define DDR_CS_SIZE 0x80000000 +#define SECURAM_SIZE 0x00004000 +#define SDMMC0_SIZE 0x00004000 +#define SDMMC1_SIZE 0x00004000 +#define SDMMC2_SIZE 0x00004000 +#define APB_DBG_S_SIZE 0x00060000 +#define APB_DBG_SIZE 0x00001000 +#define NICGPV_SIZE 0x00100000 +#define OTPC_SIZE 0x00001000 +#define CSI2DC_META_SIZE 0x00002000 +#define ARM_PERIPH_SIZE 0x00008000 +#define PERIPHERALS_SIZE 0x10000000 + +#define IROM_ADDR 0x00000000 +#define ECC_ROM_ADDR 0x00020000 +#define CPKCC_ROM_ADDR 0x00040000 +#define CPKCC_RAM_ADDR 0x00051000 +#define IRAM_ADDR 0x00100000 +#define UDPHS_RAMA_ADDR 0x00200000 +#define UDPHS_RAMB_ADDR 0x00300000 +#define UHPHS_OHCI_ADDR 0x00400000 +#define UHPHS_EHCI_ADDR 0x00500000 +#define NFC_RAM_ADDR 0x00600000 +#define NFC_ADDR 0x10000000 +#define QSPIMEM0_ADDR 0x20000000 +#define QSPIMEM1_ADDR 0x30000000 +#define EBI_CS0_ADDR 0x40000000 +#define EBI_CS1_ADDR 0x48000000 +#define EBI_CS2_ADDR 0x50000000 +#define EBI_CS3_ADDR 0x58000000 +#define DDR_CS_ADDR 0x60000000 +#define SECURAM_ADDR 0xe0000000 +#define SDMMC0_ADDR 0xe1204000 +#define SDMMC1_ADDR 0xe1208000 +#define SDMMC2_ADDR 0xe120c000 +#define APB_DBG_S_ADDR 0xe8800000 +#define APB_DBG_ADDR 0xe8900000 +#define NICGPV_ADDR 0xe8b00000 +#define OTPC_ADDR 0xe8c00000 +#define CSI2DC_META_ADDR 0xe8c02000 +#define ARM_PERIPH_ADDR 0xe8c10000 +#define PERIPHERALS_ADDR 0xe0000000 + +/* ************************************************************************** */ +/* DEVICE SIGNATURES FOR SAMA7G54 */ +/* ************************************************************************** */ +#define CHIP_JTAGID 0X05B4203F +#define CHIP_CIDR 0X80162110 +#define CHIP_EXID 0X00000000 + +#endif /* _SAMA7G54_H_ */ + diff --git a/core/arch/arm/plat-stm/main.c b/core/arch/arm/plat-stm/main.c index c2bc86897cac74b44c983412707dca98b040a1f1..f0657cb83080ead1cb4dc294b54ab5776a7f615b 100644 --- a/core/arch/arm/plat-stm/main.c +++ b/core/arch/arm/plat-stm/main.c @@ -139,5 +139,5 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk index 058199a489c6af644d959ae11eb20c3c3bae76ef..a629c0803b298e79b099b6fd523f45c39bf47b5f 100644 --- a/core/arch/arm/plat-stm32mp1/conf.mk +++ b/core/arch/arm/plat-stm32mp1/conf.mk @@ -5,17 +5,25 @@ flavor_dts_file-157C_DHCOM_PDK2 = stm32mp157c-dhcom-pdk2.dts flavor_dts_file-157C_DK2 = stm32mp157c-dk2.dts flavor_dts_file-157C_ED1 = stm32mp157c-ed1.dts flavor_dts_file-157C_EV1 = stm32mp157c-ev1.dts +flavor_dts_file-157A_DK1_SCMI = stm32mp157a-dk1-scmi.dts +flavor_dts_file-157C_DK2_SCMI = stm32mp157c-dk2-scmi.dts +flavor_dts_file-157C_ED1_SCMI = stm32mp157c-ed1-scmi.dts +flavor_dts_file-157C_EV1_SCMI = stm32mp157c-ev1-scmi.dts flavor_dts_file-135F_DK = stm32mp135f-dk.dts flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \ + $(flavor_dts_file-157C_DK2_SCMI) \ $(flavor_dts_file-135F_DK) -flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) +flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) \ + $(flavor_dts_file-157A_DK1_SCMI) flavorlist-cryp-1G = $(flavor_dts_file-157C_DHCOM_PDK2) \ $(flavor_dts_file-157C_ED1) \ - $(flavor_dts_file-157C_EV1) + $(flavor_dts_file-157C_EV1) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) flavorlist-no_cryp-1G = $(flavor_dts_file-157A_DHCOR_AVENGER96) @@ -31,14 +39,22 @@ flavorlist-1G = $(flavorlist-cryp-1G) \ flavorlist-MP15-HUK-DT = $(flavor_dts_file-157A_DK1) \ $(flavor_dts_file-157C_DK2) \ $(flavor_dts_file-157C_ED1) \ - $(flavor_dts_file-157C_EV1) + $(flavor_dts_file-157C_EV1) \ + $(flavor_dts_file-157A_DK1_SCMI) \ + $(flavor_dts_file-157C_DK2_SCMI) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) flavorlist-MP15 = $(flavor_dts_file-157A_DHCOR_AVENGER96) \ $(flavor_dts_file-157A_DK1) \ $(flavor_dts_file-157C_DHCOM_PDK2) \ $(flavor_dts_file-157C_DK2) \ $(flavor_dts_file-157C_ED1) \ - $(flavor_dts_file-157C_EV1) + $(flavor_dts_file-157C_EV1) \ + $(flavor_dts_file-157A_DK1_SCMI) \ + $(flavor_dts_file-157C_DK2_SCMI) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) flavorlist-MP13 = $(flavor_dts_file-135F_DK) @@ -99,13 +115,15 @@ $(call force,CFG_DRIVERS_REGULATOR,y) $(call force,CFG_GIC,y) $(call force,CFG_INIT_CNTVOFF,y) $(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_REGULATOR_FIXED,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_SM_PLATFORM_HANDLER,y) $(call force,CFG_STM32_SHARED_IO,y) -$(call force,CFG_REGULATOR_FIXED,y) ifeq ($(CFG_STM32MP13),y) $(call force,CFG_BOOT_SECONDARY_REQUEST,n) +$(call force,CFG_CORE_ASYNC_NOTIF,y) +$(call force,CFG_CORE_ASYNC_NOTIF_GIC_INTID,31) $(call force,CFG_CORE_RESERVED_SHM,n) $(call force,CFG_DRIVERS_CLK_FIXED,y) $(call force,CFG_SECONDARY_INIT_CNTFRQ,n) @@ -114,22 +132,24 @@ $(call force,CFG_STM32_VREFBUF,y) $(call force,CFG_STM32MP_CLK_CORE,y) $(call force,CFG_STM32MP1_SHARED_RESOURCES,n) $(call force,CFG_STM32MP13_CLK,y) +$(call force,CFG_STM32MP13_REGULATOR_IOD,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_WITH_NSEC_GPIOS,n) CFG_EXTERNAL_DT ?= n CFG_STM32MP_OPP_COUNT ?= 2 -CFG_STM32MP1_SCMI_SHM_SYSRAM ?= y CFG_WITH_PAGER ?= n endif # CFG_STM32MP13 ifeq ($(CFG_STM32MP15),y) $(call force,CFG_BOOT_SECONDARY_REQUEST,y) $(call force,CFG_DRIVERS_CLK_FIXED,n) +$(call force,CFG_HALT_CORES_ON_PANIC_SGI,15) $(call force,CFG_SECONDARY_INIT_CNTFRQ,y) $(call force,CFG_STM32MP1_SHARED_RESOURCES,y) $(call force,CFG_STM32_SAES,n) $(call force,CFG_STM32MP15_CLK,y) -CFG_CORE_RESERVED_SHM ?= y +CFG_CORE_RESERVED_SHM ?= n +CFG_HALT_CORES_ON_PANIC ?= y CFG_EXTERNAL_DT ?= y CFG_STM32_BSEC_SIP ?= y CFG_TEE_CORE_NB_CORE ?= 2 @@ -145,6 +165,16 @@ CFG_MMAP_REGIONS ?= 23 CFG_DTB_MAX_SIZE ?= (256 * 1024) CFG_CORE_ASLR ?= n +CFG_STM32MP_REMOTEPROC ?= n +CFG_DRIVERS_REMOTEPROC ?= $(CFG_STM32MP_REMOTEPROC) +CFG_REMOTEPROC_PTA ?= $(CFG_STM32MP_REMOTEPROC) +ifeq ($(CFG_REMOTEPROC_PTA),y) +# Remoteproc early TA for coprocessor firmware management in boot stages +CFG_IN_TREE_EARLY_TAS += remoteproc/80a4c275-0a47-4905-8285-1486a9771a08 +# Embed public part of this key in OP-TEE OS +RPROC_SIGN_KEY ?= keys/default.pem +endif + ifneq ($(CFG_WITH_LPAE),y) # Without LPAE, default TEE virtual address range is 1MB, we need at least 2MB. CFG_TEE_RAM_VA_SIZE ?= 0x00200000 @@ -207,6 +237,7 @@ CFG_STPMIC1 ?= y CFG_TZC400 ?= y CFG_DRIVERS_I2C ?= $(CFG_STM32_I2C) +CFG_REGULATOR_GPIO ?= $(CFG_STM32_GPIO) CFG_WITH_SOFTWARE_PRNG ?= n ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) @@ -227,6 +258,8 @@ CFG_DRIVERS_RSTCTRL ?= $(CFG_STM32_RSTCTRL) $(eval $(call cfg-depends-all,CFG_STM32_RSTCTRL,CFG_DRIVERS_RSTCTRL)) CFG_WDT ?= $(CFG_STM32_IWDG) +CFG_WDT_SM_HANDLER ?= $(CFG_WDT) +CFG_WDT_SM_HANDLER_ID ?= 0xbc000000 # Platform specific configuration CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c index 893e5dcfa632f6cf6f828b8c1f0930a75b0c1d9a..42735b8985e54c341f10af00f8c9ae3076d63b3d 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c @@ -47,12 +47,14 @@ static_assert(PMIC_REGU_FLAG_COUNT <= UINT_MAX); * struct pmic_regulator_data - Platform specific data * @flags: Flags for platform property to apply * @regu_name: Regulator name ID in stpmic1 driver - * @supported_voltages: Supported levels description or NULL is not yet built + * @voltages_desc: Supported levels description + * @voltages_level: Pointer to supported levels or NULL if not yet allocated */ struct pmic_regulator_data { unsigned int flags; char *regu_name; - struct regulator_voltages *voltages; + struct regulator_voltages_desc voltages_desc; + int *voltages_level; }; /* Expect a single PMIC instance */ @@ -395,10 +397,9 @@ static int cmp_int_value(const void *a, const void *b) return CMP_TRILEAN(*ia, *ib); } -static size_t refine_levels_array(struct regulator_voltages *voltages) +static size_t refine_levels_array(size_t count, int *levels_uv, + int min_uv, int max_uv) { - int *levels_uv = voltages->entries; - size_t count = voltages->num_levels; size_t n = 0; size_t m = 0; @@ -413,20 +414,34 @@ static size_t refine_levels_array(struct regulator_voltages *voltages) m++; } } + count = m + 1; - return m + 1; + for (n = count; n; n--) + if (levels_uv[n - 1] <= max_uv) + break; + count = n; + + for (n = 0; n < count; n++) + if (levels_uv[n] >= min_uv) + break; + count -= n; + + memmove(levels_uv, levels_uv + n, count * sizeof(*levels_uv)); + + return count; } static TEE_Result pmic_list_voltages(struct regulator *regulator, - struct regulator_voltages **out_voltages) + struct regulator_voltages_desc **out_desc, + const int **out_levels) { struct pmic_regulator_data *priv = regulator->priv; - if (!priv->voltages) { - struct regulator_voltages *voltages_s = NULL; - struct regulator_voltages *voltages = NULL; + if (!priv->voltages_level) { const uint16_t *level_ref = NULL; size_t level_count = 0; + int *levels2 = NULL; + int *levels = NULL; size_t n = 0; /* @@ -436,30 +451,30 @@ static TEE_Result pmic_list_voltages(struct regulator *regulator, stpmic1_regulator_levels_mv(priv->regu_name, &level_ref, &level_count); - voltages = calloc(1, sizeof(*voltages) + - sizeof(*voltages->entries) * level_count); - if (!voltages) + levels = calloc(level_count, sizeof(*levels)); + if (!levels) return TEE_ERROR_OUT_OF_MEMORY; for (n = 0; n < level_count; n++) - voltages->entries[n] = level_ref[n] * 1000; + levels[n] = level_ref[n] * 1000; - voltages->num_levels = level_count; - level_count = refine_levels_array(voltages); + level_count = refine_levels_array(level_count, levels, + regulator->min_uv, + regulator->max_uv); - voltages_s = realloc(voltages, - sizeof(*voltages) + - sizeof(*voltages->entries) * level_count); - if (!voltages_s) { - free(voltages); + /* Shrink levels array to not waste heap memory */ + levels2 = realloc(levels, sizeof(*levels) * level_count); + if (!levels2) { + free(levels); return TEE_ERROR_OUT_OF_MEMORY; } - voltages_s->type = VOLTAGE_TYPE_FULL_LIST; - voltages_s->num_levels = level_count; - priv->voltages = voltages_s; + priv->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; + priv->voltages_desc.num_levels = level_count; + priv->voltages_level = levels2; } - *out_voltages = priv->voltages; + *out_desc = &priv->voltages_desc; + *out_levels = priv->voltages_level; return TEE_SUCCESS; } @@ -535,8 +550,8 @@ static TEE_Result release_voltage_lists(void) for (n = 0; n < ARRAY_SIZE(pmic_regulators); n++) { struct pmic_regulator_data *priv = pmic_regulators[n].priv; - if (priv && priv->voltages) - free(priv->voltages); + if (priv && priv->voltages_level) + free(priv->voltages_level); } return TEE_SUCCESS; diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c index 4785c9db1cb7ae4cb7a7b4f58018c30b0a6be66d..e06e2a2b1fe0e64b7b667b36fafe4f8e179c31a0 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c @@ -6,11 +6,14 @@ #include <assert.h> #include <drivers/regulator.h> #include <drivers/stm32_shared_io.h> +#include <drivers/stm32_bsec.h> #include <drivers/stm32mp1_pwr.h> +#include <drivers/stm32mp1_syscfg.h> #include <io.h> #include <kernel/delay.h> #include <kernel/dt_driver.h> #include <kernel/panic.h> +#include <kernel/pm.h> #include <libfdt.h> #include <mm/core_memprot.h> #include <platform_config.h> @@ -24,6 +27,8 @@ #define TIMEOUT_US_10MS U(10000) +#define VOLTAGE_2V7_THREDSHOLD_UV 2700000 + struct pwr_regu_desc { unsigned int level_mv; uint32_t cr3_enable_mask; @@ -100,19 +105,17 @@ static TEE_Result stm32mp1_pwr_regu_set_state(struct regulator *regu, { const struct pwr_regu_desc *desc = regu->priv; uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF; - uint64_t to = 0; assert(desc); if (enable) { - io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask); + uint32_t value = 0; - to = timeout_init_us(TIMEOUT_US_10MS); - while (!timeout_elapsed(to)) - if (io_read32(cr3) & desc->cr3_ready_mask) - break; + io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask); - if (!(io_read32(cr3) & desc->cr3_ready_mask)) + if (IO_READ32_POLL_TIMEOUT(cr3, value, + value & desc->cr3_ready_mask, + 0, TIMEOUT_US_10MS)) return TEE_ERROR_GENERIC; } else { io_clrbits32_stm32shregs(cr3, desc->cr3_enable_mask); @@ -178,13 +181,81 @@ struct regulator *stm32mp1_pwr_get_regulator(enum pwr_regulator id) return NULL; } +static TEE_Result vdd_hslv_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *pm_hdl __unused) +{ + if (op == PM_OP_RESUME) + stm32mp_enable_fixed_vdd_hslv(); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(vdd_hslv_pm); + +static TEE_Result set_fixed_vdd_hslv_mode(struct regulator *vdd_supply) +{ + TEE_Result res = TEE_ERROR_GENERIC; + bool product_below_2v5 = false; + uint32_t otp_value = 0; + uint32_t otp_id = 0; + + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. + * It could be disabled for low frequencies or if AFMUX is selected + * but the function is not used, typically for TRACE. + * If high speed low voltage pad mode is enabled, platform will + * over consume. + * + * WARNING: + * Enabling High Speed mode while Vdd > 2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the SoC. + */ + res = stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id, + NULL, NULL); + if (res) + panic(); + + res = stm32_bsec_read_otp(&otp_value, otp_id); + if (res) + panic(); + + if (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) + product_below_2v5 = true; + + if (regulator_get_voltage(vdd_supply) < VOLTAGE_2V7_THREDSHOLD_UV) { + if (!product_below_2v5) { + DMSG("Vdd domains HSLV protected by HW"); + } else { + stm32mp_enable_fixed_vdd_hslv(); + register_pm_driver_cb(vdd_hslv_pm, NULL, + "stm32mp1-pwr-hslv"); + } + } else if (product_below_2v5) { + panic("Vdd too high for related IO domains"); + } + + return TEE_SUCCESS; +} + static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; const struct regu_dt_desc *dt_desc = stm32mp1_pwr_regu_dt_desc; + struct regulator *vdd_supply = NULL; int subnode = 0; + /* Setup High Speed Low Voltage mode for fixed VDD domain */ + res = regulator_dt_get_supply(fdt, node, "vdd", &vdd_supply); + if (res) + return res; + + res = set_fixed_vdd_hslv_mode(vdd_supply); + if (res) + return res; + + /* Register PWR regulators */ fdt_for_each_subnode(subnode, fdt, node) { const char *node_name = fdt_get_name(fdt, subnode, NULL); unsigned int n = 0; @@ -198,14 +269,10 @@ static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node, panic(); } - if (IS_ENABLED(CFG_DRIVERS_REGULATOR)) { - res = regulator_dt_register(fdt, subnode, node, - dt_desc + n); - if (res) { - EMSG("Can't register %s: %#"PRIx32, node_name, - res); - panic(); - } + res = regulator_dt_register(fdt, subnode, node, dt_desc + n); + if (res) { + EMSG("Can't register %s: %#"PRIx32, node_name, res); + panic(); } } diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h index 65718a05a6ffe5d7468dd4f126e99ca6491803de..d6dc5de21c9454f3d05dd72fa974a7139f150b8d 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause */ /* - * Copyright (c) 2018-2019, STMicroelectronics + * Copyright (c) 2018-2023, STMicroelectronics */ #ifndef __STM32MP1_PWR_H @@ -17,6 +17,14 @@ #define PWR_WKUPCR_OFF 0x20 #define PWR_MPUWKUPENR_OFF 0x28 +/* CR3 register bitfield for STM32MP13 variants */ +#define PWR_CR3_VDDSD1EN BIT(13) +#define PWR_CR3_VDDSD1RDY BIT(14) +#define PWR_CR3_VDDSD2EN BIT(15) +#define PWR_CR3_VDDSD2RDY BIT(16) +#define PWR_CR3_VDDSD1VALID BIT(22) +#define PWR_CR3_VDDSD2VALID BIT(23) + #define PWR_OFFSET_MASK 0x3fUL enum pwr_regulator { diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c index 281ae7caae55cc389deba717a93025ba75a940db..1b2ecbcffab37d3450c56c8a000b4358de016b12 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2019-2022, STMicroelectronics + * Copyright (c) 2019-2023, STMicroelectronics */ +#include <config.h> #include <drivers/clk.h> #include <drivers/stm32mp_dt_bindings.h> +#include <drivers/stm32mp1_syscfg.h> #include <initcall.h> #include <kernel/delay.h> #include <mm/core_memprot.h> @@ -16,8 +18,22 @@ /* * SYSCFG register offsets (base relative) */ -#define SYSCFG_CMPCR 0x20U -#define SYSCFG_CMPENSETR 0x24U +#define SYSCFG_IOCTRLSETR U(0x18) +#define SYSCFG_CMPCR U(0x20) +#define SYSCFG_CMPENSETR U(0x24) +#define SYSCFG_CMPSD1CR U(0x30) +#define SYSCFG_CMPSD2CR U(0x40) +#define SYSCFG_HSLVEN0R U(0x50) +#define SYSCFG_IOSIZE U(0x400) + +/* + * SYSCFG_IOCTRLSETR Register for STM32MP15 variants + */ +#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) +#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) +#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) +#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) +#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) /* * SYSCFG_CMPCR Register @@ -25,78 +41,159 @@ #define SYSCFG_CMPCR_SW_CTRL BIT(1) #define SYSCFG_CMPCR_READY BIT(8) #define SYSCFG_CMPCR_RANSRC GENMASK_32(19, 16) -#define SYSCFG_CMPCR_RANSRC_SHIFT 16 +#define SYSCFG_CMPCR_RANSRC_SHIFT U(16) #define SYSCFG_CMPCR_RAPSRC GENMASK_32(23, 20) -#define SYSCFG_CMPCR_ANSRC_SHIFT 24 +#define SYSCFG_CMPCR_ANSRC_SHIFT U(24) -#define SYSCFG_CMPCR_READY_TIMEOUT_US 1000U +#define SYSCFG_CMPCR_READY_TIMEOUT_US U(1000) + +#define CMPENSETR_OFFSET U(0x4) +#define CMPENCLRR_OFFSET U(0x8) /* * SYSCFG_CMPENSETR Register */ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) +/* + * HSLV definitions + */ +#define SYSCFG_HSLV_MASK GENMASK_32(15, 0) +#define SYSCFG_HSLV_KEY U(0x1018) + static vaddr_t get_syscfg_base(void) { - struct io_pa_va base = { .pa = SYSCFG_BASE }; + static struct io_pa_va base = { .pa = SYSCFG_BASE }; - return io_pa_or_va(&base, 1); + return io_pa_or_va(&base, SYSCFG_IOSIZE); } -void stm32mp_syscfg_enable_io_compensation(void) +static void enable_io_compensation(int cmpcr_offset) { - vaddr_t syscfg_base = get_syscfg_base(); - uint64_t timeout_ref = 0; + vaddr_t cmpcr_va = get_syscfg_base() + cmpcr_offset; + uint32_t value = 0; + + if (io_read32(cmpcr_va) & SYSCFG_CMPCR_READY) + return; + + io_setbits32(cmpcr_va + CMPENSETR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); + + if (IO_READ32_POLL_TIMEOUT(cmpcr_va, value, value & SYSCFG_CMPCR_READY, + 0, SYSCFG_CMPCR_READY_TIMEOUT_US)) { + /* Allow an almost silent failure here */ + EMSG("IO compensation cell not ready"); + } + + io_clrbits32(cmpcr_va, SYSCFG_CMPCR_SW_CTRL); + + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_va)); +} + +static __maybe_unused void disable_io_compensation(int cmpcr_offset) +{ + vaddr_t cmpcr_base = get_syscfg_base() + cmpcr_offset; + uint32_t value_cmpcr = 0; + uint32_t apsrc_ansrc = 0; + uint32_t value_cmpcr2 = 0; + + value_cmpcr = io_read32(cmpcr_base); + value_cmpcr2 = io_read32(cmpcr_base + CMPENSETR_OFFSET); + if (!(value_cmpcr & SYSCFG_CMPCR_READY && + value_cmpcr2 & SYSCFG_CMPENSETR_MPU_EN)) + return; + + /* Copy APSRC (resp. ANSRC) in RAPSRC (resp. RANSRC) */ + apsrc_ansrc = value_cmpcr >> SYSCFG_CMPCR_ANSRC_SHIFT; + value_cmpcr &= ~(SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + value_cmpcr |= SHIFT_U32(apsrc_ansrc, SYSCFG_CMPCR_RANSRC_SHIFT); + + io_write32(cmpcr_base, value_cmpcr | SYSCFG_CMPCR_SW_CTRL); + + io_setbits32(cmpcr_base + CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_base)); +} + +static TEE_Result stm32mp1_iocomp(void) +{ if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) || clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG))) panic(); - io_setbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); + enable_io_compensation(SYSCFG_CMPCR); - timeout_ref = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); + return TEE_SUCCESS; +} - while (!(io_read32(syscfg_base + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY)) { - if (timeout_elapsed(timeout_ref)) { - EMSG("IO compensation cell not ready"); - /* Allow an almost silent failure here */ - break; - } - } +driver_init(stm32mp1_iocomp); - io_clrbits32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); +#ifdef CFG_STM32MP13 +void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable) +{ + int cmpcr_offset = 0; + + switch (id) { + case SYSCFG_IO_COMP_IDX_SD1: + cmpcr_offset = SYSCFG_CMPSD1CR; + break; + case SYSCFG_IO_COMP_IDX_SD2: + cmpcr_offset = SYSCFG_CMPSD2CR; + break; + default: + panic(); + } - DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR)); + if (enable) + enable_io_compensation(cmpcr_offset); + else + disable_io_compensation(cmpcr_offset); } -void stm32mp_syscfg_disable_io_compensation(void) +void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable) { - vaddr_t syscfg_base = get_syscfg_base(); - uint32_t value = 0; + size_t hslvenxr_offset = 0; + uint32_t hlvs_value = 0; - value = io_read32(syscfg_base + SYSCFG_CMPCR) >> - SYSCFG_CMPCR_ANSRC_SHIFT; + assert(id < SYSCFG_HSLV_COUNT); - io_clrbits32(syscfg_base + SYSCFG_CMPCR, - SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + if (enable) + hlvs_value = SYSCFG_HSLV_KEY; - value = io_read32(syscfg_base + SYSCFG_CMPCR) | - (value << SYSCFG_CMPCR_RANSRC_SHIFT); + /* IDs are indices of SYSCFG_HSLVENxR registers */ + hslvenxr_offset = SYSCFG_HSLVEN0R + id * sizeof(uint32_t); - io_write32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); + io_write32(get_syscfg_base() + hslvenxr_offset, hlvs_value); - DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR)); + /* Value read shall be 1 on enable and 0 on disable */ + hlvs_value = io_read32(get_syscfg_base() + hslvenxr_offset) & + SYSCFG_HSLV_MASK; + if (enable != hlvs_value) + panic(); +} + +void stm32mp_enable_fixed_vdd_hslv(void) +{ + enum stm32mp13_hslv_id id = SYSCFG_HSLV_COUNT; - io_clrbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); + for (id = SYSCFG_HSLV_IDX_TPIU; id < SYSCFG_HSLV_COUNT; id++) { + /* SDMMCs domains may not be supplied by VDD */ + if (id == SYSCFG_HSLV_IDX_SDMMC1 || + id == SYSCFG_HSLV_IDX_SDMMC2) + continue; - clk_disable(stm32mp_rcc_clock_id_to_clk(CK_CSI)); - clk_disable(stm32mp_rcc_clock_id_to_clk(SYSCFG)); + stm32mp_set_hslv_state(id, true); + } } +#endif /* CFG_STM32MP13 */ -static TEE_Result stm32mp1_iocomp(void) +#ifdef CFG_STM32MP15 +void stm32mp_enable_fixed_vdd_hslv(void) { - stm32mp_syscfg_enable_io_compensation(); - - return TEE_SUCCESS; + io_write32(get_syscfg_base() + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI); } -driver_init(stm32mp1_iocomp); +#endif diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h new file mode 100644 index 0000000000000000000000000000000000000000..575f147be1fe3e1f5ec022443c43b50aafdb5388 --- /dev/null +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32MP1_SYSCFG_H +#define __DRIVERS_STM32MP1_SYSCFG_H + +/* High Speed Low Voltage domains IDs for STM32MP13 variants */ +enum stm32mp13_hslv_id { + SYSCFG_HSLV_IDX_TPIU = 0, + SYSCFG_HSLV_IDX_QSPI, + SYSCFG_HSLV_IDX_ETH1, + SYSCFG_HSLV_IDX_ETH2, + SYSCFG_HSLV_IDX_SDMMC1, + SYSCFG_HSLV_IDX_SDMMC2, + SYSCFG_HSLV_IDX_SPI1, + SYSCFG_HSLV_IDX_SPI2, + SYSCFG_HSLV_IDX_SPI3, + SYSCFG_HSLV_IDX_SPI4, + SYSCFG_HSLV_IDX_SPI5, + SYSCFG_HSLV_IDX_LTDC, + SYSCFG_HSLV_COUNT +}; + +/* IO compensation domains IDs for STM32MP13 variants */ +enum stm32mp13_vddsd_comp_id { + SYSCFG_IO_COMP_IDX_SD1, + SYSCFG_IO_COMP_IDX_SD2, + SYSCFG_IO_COMP_COUNT +}; + +#ifdef CFG_STM32MP13 +/* + * Enable or disable IO compensation for a VDDSD IO domains + * @id: VDDSD domain ID + * @enable: True to enable IO compensation, false to disable + */ +void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable); + +/* + * Enable or disable High Speed Low Voltage mode of an IO domain + * @index: HSLV IO domain ID + * @enable: True to enable IO compensation, false to disable + */ +void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable); +#endif /*CFG_STM32MP13*/ + +/* Enable High Speed Low Voltage mode for domains fixed supplied VDD */ +void stm32mp_enable_fixed_vdd_hslv(void); +#endif /*__DRIVERS_STM32MP1_SYSCFG_H*/ diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c index eebf0bd5e505f1651cc68364d05246ffa3ca51af..eed6b77c238350f917253f9af9f4fda63cdc2dcd 100644 --- a/core/arch/arm/plat-stm32mp1/main.c +++ b/core/arch/arm/plat-stm32mp1/main.c @@ -160,7 +160,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); stm32mp_register_online_cpu(); } @@ -500,16 +500,6 @@ static bool __maybe_unused bank_is_valid(unsigned int bank) panic(); } -unsigned int stm32_get_gpio_bank_offset(unsigned int bank) -{ - assert(bank_is_valid(bank)); - - if (bank == GPIO_BANK_Z) - return 0; - - return bank * GPIO_BANK_OFFSET; -} - #ifdef CFG_STM32_IWDG TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, struct stm32_iwdg_otp_data *otp_data) @@ -563,7 +553,7 @@ static TEE_Result init_debug(void) return res; if (state != BSEC_STATE_SEC_CLOSED && conf) { - if (IS_ENABLED(CFG_WARN_INSECURE)) + if (IS_ENABLED(CFG_INSECURE)) IMSG("WARNING: All debug accesses are allowed"); res = stm32_bsec_write_debug_conf(conf | BSEC_DEBUG_ALL); diff --git a/core/arch/arm/plat-stm32mp1/plat_tzc400.c b/core/arch/arm/plat-stm32mp1/plat_tzc400.c index 55f6d41d5a3b3b3ec7a601c6173cb6f345da2982..25c75b93c0ef931114a4bc7a829746c9030c1f52 100644 --- a/core/arch/arm/plat-stm32mp1/plat_tzc400.c +++ b/core/arch/arm/plat-stm32mp1/plat_tzc400.c @@ -40,11 +40,12 @@ static struct itr_handler tzc_itr_handler = { }; DECLARE_KEEP_PAGER(tzc_itr_handler); -static bool tzc_region_is_non_secure(unsigned int i, vaddr_t base, size_t size) +static bool tzc_region_is_non_secure(unsigned int i, uint64_t pa, size_t size) { struct tzc_region_config region_cfg = { }; uint32_t ns_cpu_mask = TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID); uint32_t filters_mask = TZC_FILTERS_MASK; + vaddr_t base = pa; if (tzc_get_region_config(i, ®ion_cfg)) panic(); @@ -71,6 +72,7 @@ static bool tzc_region_is_secure(unsigned int i, vaddr_t base, size_t size) static TEE_Result init_stm32mp1_tzc(void) { + TEE_Result res = TEE_ERROR_GENERIC; void *base = phys_to_virt(TZC_BASE, MEM_AREA_IO_SEC, 1); unsigned int region_index = 1; const uint64_t dram_start = DDR_BASE; @@ -108,8 +110,12 @@ static TEE_Result init_stm32mp1_tzc(void) panic("Unexpected TZC area on non-secure region"); } - itr_add(&tzc_itr_handler); - itr_enable(tzc_itr_handler.it); + res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &tzc_itr_handler); + if (res) + panic(); + + interrupt_enable(tzc_itr_handler.chip, tzc_itr_handler.it); tzc_set_action(TZC_ACTION_INT); return TEE_SUCCESS; diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h index 3c87a37abfda1112b4682ce102f3e0eb6bc075d1..c3867fc8ed212cd6f5402c015a5d70cebe6d674e 100644 --- a/core/arch/arm/plat-stm32mp1/platform_config.h +++ b/core/arch/arm/plat-stm32mp1/platform_config.h @@ -135,6 +135,8 @@ #define HW2_OTP_IWDG_FZ_STOP_SHIFT U(5) #define HW2_OTP_IWDG_FZ_STANDBY_SHIFT U(7) +#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + /* GIC resources */ #define GIC_SIZE 0x2000 #define GICC_OFFSET 0x1000 diff --git a/core/arch/arm/plat-stm32mp1/pm/psci.c b/core/arch/arm/plat-stm32mp1/pm/psci.c index f39c032b2f41e9024b2070f34ef2a7a68125bf05..bb206808df14ed9a2b9dc12fc42d7378b7968a55 100644 --- a/core/arch/arm/plat-stm32mp1/pm/psci.c +++ b/core/arch/arm/plat-stm32mp1/pm/psci.c @@ -132,6 +132,8 @@ static void raise_sgi0_as_secure(void) static void release_secondary_early_hpen(size_t __unused pos) { + struct itr_chip *itr_chip = interrupt_get_main_chip(); + /* Need to send SIG#0 over Group0 after individual core 1 reset */ raise_sgi0_as_secure(); udelay(20); @@ -142,7 +144,7 @@ static void release_secondary_early_hpen(size_t __unused pos) BOOT_API_A7_CORE1_MAGIC_NUMBER); dsb_ishst(); - itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); + interrupt_raise_sgi(itr_chip, GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); } /* Override default psci_cpu_on() with platform specific sequence */ diff --git a/core/arch/arm/plat-stm32mp1/scmi_server.c b/core/arch/arm/plat-stm32mp1/scmi_server.c index 857809e774ca0f117ecdfbc43897af0e3e39b0b1..b0cc34b5d858f8ad23cdaa0b5794a1c399656314 100644 --- a/core/arch/arm/plat-stm32mp1/scmi_server.c +++ b/core/arch/arm/plat-stm32mp1/scmi_server.c @@ -14,6 +14,7 @@ #include <drivers/stm32_vrefbuf.h> #include <drivers/stm32mp1_pmic.h> #include <drivers/stm32mp1_pwr.h> +#include <drivers/stm32mp13_regulator_iod.h> #include <drivers/stpmic1.h> #include <drivers/stpmic1_regulator.h> #include <drivers/stm32mp_dt_bindings.h> @@ -63,21 +64,22 @@ enum voltd_device { VOLTD_PWR, VOLTD_PMIC, VOLTD_VREFBUF, - /* Stub regulator until regulator framework is merged */ - VOLTD_STUB, + VOLTD_IOD, }; /* * struct stm32_scmi_voltd - Data for the exposed voltage domains * @name: Power regulator string ID exposed to channel - * @priv_id: Internal string ID for the regulator + * @priv_name: Internal string ID for the PMIC regulators + * @priv_id: Internal ID for the regulator aside PMIC ones * @priv_dev: Internal ID for the device implementing the regulator * @regulator: Regulator controller device * @state: State of the SCMI voltage domain (true: enable, false: disable) */ struct stm32_scmi_voltd { const char *name; - const char *priv_id; + const char *priv_name; + unsigned int priv_id; enum voltd_device priv_dev; struct regulator *regulator; bool state; @@ -109,13 +111,26 @@ register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE, .name = (_name), \ } -#define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _name) \ +#define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _priv_name, _name) \ [(_scmi_id)] = { \ + .priv_name = (_priv_name), \ .priv_id = (_priv_id), \ .priv_dev = (_dev_id), \ .name = (_name), \ } +#define VOLTD_CELL_PWR(_scmi_id, _priv_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_PWR, (_priv_id), NULL, (_name)) + +#define VOLTD_CELL_IOD(_scmi_id, _priv_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_IOD, (_priv_id), NULL, (_name)) + +#define VOLTD_CELL_VREFBUF(_scmi_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_VREFBUF, 0, NULL, (_name)) + +#define VOLTD_CELL_PMIC(_scmi_id, _priv_name, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_PMIC, 0, (_priv_name), (_name)) + #ifdef CFG_STM32MP13 static struct stm32_scmi_clk stm32_scmi_clock[] = { CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true), @@ -201,65 +216,50 @@ static struct stm32_scmi_rd stm32_scmi_reset_domain[] = { }; #endif -#define PWR_REG11_NAME_ID "0" -#define PWR_REG18_NAME_ID "1" -#define PWR_USB33_NAME_ID "2" - -#define STUB_SDMMC1_IO_NAME_ID "sdmmc1" -#define STUB_SDMMC2_IO_NAME_ID "sdmmc2" - #ifdef CFG_STM32MP13 struct stm32_scmi_voltd scmi_voltage_domain[] = { - VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"), - VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"), - VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"), - VOLTD_CELL(VOLTD_SCMI_SDMMC1_IO, VOLTD_STUB, STUB_SDMMC1_IO_NAME_ID, - "sdmmc1"), - VOLTD_CELL(VOLTD_SCMI_SDMMC2_IO, VOLTD_STUB, STUB_SDMMC2_IO_NAME_ID, - "sdmmc2"), - VOLTD_CELL(VOLTD_SCMI_VREFBUF, VOLTD_VREFBUF, "vrefbuf", "vrefbuf"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "buck1"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "buck2"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "buck3"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "buck4"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "ldo1"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "ldo2"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "ldo3"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "ldo4"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "ldo5"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "ldo6"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr", - "vref_ddr"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1", - "pwr_sw1"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2", - "pwr_sw2"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), + VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), + VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC1_IO, IOD_SDMMC1, "sdmmc1"), + VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC2_IO, IOD_SDMMC2, "sdmmc2"), + VOLTD_CELL_VREFBUF(VOLTD_SCMI_VREFBUF, "vrefbuf"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "buck1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "buck2"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "buck3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "buck4"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "ldo1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "ldo2"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "ldo3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "ldo4"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "ldo5"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "ldo6"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "pwr_sw1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "pwr_sw2"), }; #endif #ifdef CFG_STM32MP15 struct stm32_scmi_voltd scmi_voltage_domain[] = { - VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"), - VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"), - VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "vddcore"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "vdd_ddr"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "vdd"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "v3v3"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "v1v8_audio"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "v3v3_hdmi"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "vtt_ddr"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "vdd_usb"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "vdda"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "v1v2_hdmi"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr", - "vref_ddr"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1", - "vbus_otg"), - VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2", - "vbus_sw"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), + VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "vddcore"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "vdd_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "vdd"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "v3v3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "v1v8_audio"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "v3v3_hdmi"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "vtt_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "vdd_usb"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "vdda"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "v1v2_hdmi"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "vbus_otg"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "vbus_sw"), }; #endif @@ -624,48 +624,9 @@ const char *plat_scmi_voltd_get_name(unsigned int channel_id, return voltd->name; } -static enum pwr_regulator pwr_scmi_to_regu_id(struct stm32_scmi_voltd *voltd) -{ - if (!strcmp(voltd->priv_id, PWR_REG11_NAME_ID)) - return PWR_REG11; - if (!strcmp(voltd->priv_id, PWR_REG18_NAME_ID)) - return PWR_REG18; - if (!strcmp(voltd->priv_id, PWR_USB33_NAME_ID)) - return PWR_USB33; - - panic(); -} - -static long stub_get_level_uv(struct stm32_scmi_voltd *voltd) -{ - if (!strcmp(voltd->priv_id, STUB_SDMMC1_IO_NAME_ID) || - !strcmp(voltd->priv_id, STUB_SDMMC2_IO_NAME_ID)) - return 3300000; - - panic(); -} - -static int32_t stub_describe_levels(struct stm32_scmi_voltd *voltd __unused, - size_t start_index, long *microvolt, - size_t *nb_elts) -{ - if (start_index) - return SCMI_INVALID_PARAMETERS; - - if (!microvolt || !*nb_elts) { - *nb_elts = 1; - return SCMI_SUCCESS; - } - - microvolt[0] = stub_get_level_uv(voltd); - *nb_elts = 1; - - return SCMI_SUCCESS; -} - int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, - long *levels, size_t *nb_elts) + long *out_levels, size_t *nb_elts) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); @@ -674,18 +635,18 @@ int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, return SCMI_NOT_FOUND; if (voltd->regulator) { - struct regulator_voltages *voltages = NULL; + struct regulator_voltages_desc *desc = NULL; TEE_Result res = TEE_ERROR_GENERIC; - int *ref = NULL; - size_t ref_count = 0; + const int *levels = NULL; size_t n = 0; - res = regulator_supported_voltages(voltd->regulator, &voltages); + res = regulator_supported_voltages(voltd->regulator, &desc, + &levels); if (res == TEE_ERROR_NOT_SUPPORTED) return SCMI_NOT_SUPPORTED; if (res) return SCMI_GENERIC_ERROR; - if (!voltages || voltages->type != VOLTAGE_TYPE_FULL_LIST) { + if (!desc || desc->type != VOLTAGE_TYPE_FULL_LIST) { /* * Triplet min/max/step description. Caller should use * plat_scmi_voltd_levels_by_step(). @@ -693,44 +654,22 @@ int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, return SCMI_NOT_SUPPORTED; } - ref = voltages->entries; - ref_count = voltages->num_levels; - - /* Bound according to regulator registered min/max levels */ - for (n = ref_count; n > 0; n--) - if (voltages->entries[n - 1] > voltd->regulator->max_uv) - ref_count--; - for (n = 0; n < ref_count; n++) - if (voltages->entries[n] >= voltd->regulator->min_uv) - break; - - if (n == ref_count) { - DMSG("Voltage list out of regulator %s level bounds", - regulator_name(voltd->regulator)); - return SCMI_GENERIC_ERROR; - } - - if (start_index >= ref_count) + if (start_index >= desc->num_levels) return SCMI_OUT_OF_RANGE; if (!*nb_elts) { - *nb_elts = ref_count - start_index; + *nb_elts = desc->num_levels - start_index; return SCMI_SUCCESS; } + *nb_elts = MIN(*nb_elts, desc->num_levels - start_index); for (n = 0; n < *nb_elts; n++) - levels[n] = ref[start_index + n]; + out_levels[n] = levels[start_index + n]; return SCMI_SUCCESS; } - switch (voltd->priv_dev) { - case VOLTD_STUB: - return stub_describe_levels(voltd, start_index, levels, - nb_elts); - default: - return SCMI_DENIED; - } + return SCMI_DENIED; } int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, @@ -742,18 +681,17 @@ int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, return SCMI_NOT_FOUND; if (voltd->regulator) { - struct regulator_voltages *voltages = NULL; + struct regulator_voltages_desc *desc = NULL; TEE_Result res = TEE_ERROR_GENERIC; - int ref_min = 0; - int ref_max = 0; - int ref_step = 0; + const int *levels = NULL; - res = regulator_supported_voltages(voltd->regulator, &voltages); + res = regulator_supported_voltages(voltd->regulator, &desc, + &levels); if (res == TEE_ERROR_NOT_SUPPORTED) return SCMI_NOT_SUPPORTED; if (res) return SCMI_GENERIC_ERROR; - if (!voltages || voltages->type != VOLTAGE_TYPE_INCREMENT) { + if (!desc || desc->type != VOLTAGE_TYPE_INCREMENT) { /* * Triplet min/max/step description. Caller should use * plat_scmi_voltd_levels_by_step(). @@ -761,27 +699,9 @@ int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, return SCMI_NOT_SUPPORTED; } - ref_min = voltages->entries[0]; - ref_max = voltages->entries[1]; - ref_step = voltages->entries[2]; - - if (ref_min < voltd->regulator->min_uv) { - int diff = voltd->regulator->min_uv - ref_min; - int incr = DIV_ROUND_UP(diff, ref_step); - - ref_min += ref_step * incr; - } - - if (ref_max > voltd->regulator->max_uv) { - int diff = ref_max - voltd->regulator->max_uv; - int decr = diff / ref_step; - - ref_max -= ref_step * decr; - } - - min_max_step[0] = ref_min; - min_max_step[1] = ref_max; - min_max_step[2] = ref_step; + min_max_step[0] = levels[0]; + min_max_step[1] = levels[1]; + min_max_step[2] = levels[2]; return SCMI_SUCCESS; } @@ -802,13 +722,7 @@ int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, return SCMI_SUCCESS; } - switch (voltd->priv_dev) { - case VOLTD_STUB: - *level_uv = stub_get_level_uv(voltd); - return SCMI_SUCCESS; - default: - return SCMI_DENIED; - } + return SCMI_DENIED; } int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, @@ -832,12 +746,7 @@ int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, return SCMI_SUCCESS; } - switch (voltd->priv_dev) { - case VOLTD_STUB: - return SCMI_SUCCESS; - default: - return SCMI_DENIED; - } + return SCMI_DENIED; } int32_t plat_scmi_voltd_get_config(unsigned int channel_id, @@ -857,13 +766,7 @@ int32_t plat_scmi_voltd_get_config(unsigned int channel_id, return SCMI_SUCCESS; } - switch (voltd->priv_dev) { - case VOLTD_STUB: - *config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON; - return SCMI_SUCCESS; - default: - return SCMI_DENIED; - } + return SCMI_DENIED; } int32_t plat_scmi_voltd_set_config(unsigned int channel_id, @@ -875,52 +778,47 @@ int32_t plat_scmi_voltd_set_config(unsigned int channel_id, return SCMI_NOT_FOUND; if (voltd->regulator) { - TEE_Result res = TEE_ERROR_GENERIC; + switch (config) { + case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON: + if (!voltd->state) { + if (regulator_enable(voltd->regulator)) + return SCMI_GENERIC_ERROR; - if (config == SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON && - !voltd->state) { - res = regulator_enable(voltd->regulator); - if (!res) voltd->state = true; - } else if (config == SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF && - voltd->state) { - res = regulator_disable(voltd->regulator); - if (!res) + } + break; + case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF: + if (voltd->state) { + if (regulator_disable(voltd->regulator)) + return SCMI_GENERIC_ERROR; + voltd->state = false; - } else { - res = TEE_ERROR_GENERIC; + } + break; + default: + return SCMI_INVALID_PARAMETERS; } - if (res) - return SCMI_GENERIC_ERROR; - else - return SCMI_SUCCESS; - } - - switch (voltd->priv_dev) { - case VOLTD_STUB: return SCMI_SUCCESS; - default: - return SCMI_DENIED; } + + return SCMI_DENIED; } static void get_voltd_regulator(struct stm32_scmi_voltd *voltd) { - enum pwr_regulator regu_id = PWR_REGU_COUNT; - switch (voltd->priv_dev) { case VOLTD_PWR: - regu_id = pwr_scmi_to_regu_id(voltd); - voltd->regulator = stm32mp1_pwr_get_regulator(regu_id); + voltd->regulator = stm32mp1_pwr_get_regulator(voltd->priv_id); break; case VOLTD_PMIC: - voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_id); + voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_name); break; case VOLTD_VREFBUF: voltd->regulator = stm32_vrefbuf_regulator(); break; - case VOLTD_STUB: + case VOLTD_IOD: + voltd->regulator = stm32mp1_get_iod_regulator(voltd->priv_id); break; default: break; diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c index b85a1304af62a3290d9f8e25c38f276514222e25..76ce6485918bff8f9257e8b06a1cf38b21a2a484 100644 --- a/core/arch/arm/plat-stm32mp1/shared_resources.c +++ b/core/arch/arm/plat-stm32mp1/shared_resources.c @@ -692,8 +692,12 @@ static void check_rcc_secure_configuration(void) } } - if (have_error) - panic(); + if (have_error) { + if (IS_ENABLED(CFG_INSECURE)) + EMSG("WARNING: CFG_INSECURE allows insecure RCC configuration"); + else + panic(); + } } static void set_gpio_secure_configuration(void) diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h index 4ec59339aa2d8a426013b216310d4752e5ee620c..627933e4ad6a4155c01f4babc252077a6ff045bb 100644 --- a/core/arch/arm/plat-stm32mp1/stm32_util.h +++ b/core/arch/arm/plat-stm32mp1/stm32_util.h @@ -18,34 +18,12 @@ /* Backup registers and RAM utils */ vaddr_t stm32mp_bkpreg(unsigned int idx); -/* - * SYSCFG IO compensation. - * These functions assume non-secure world is suspended. - */ -void stm32mp_syscfg_enable_io_compensation(void); -void stm32mp_syscfg_disable_io_compensation(void); - /* Platform util for the RCC drivers */ vaddr_t stm32_rcc_base(void); /* Platform util for the GIC */ vaddr_t get_gicd_base(void); -/* - * Platform util functions for the GPIO driver - * @bank: Target GPIO bank ID as per DT bindings - * - * Platform shall implement these functions to provide to stm32_gpio - * driver the resource reference for a target GPIO bank. That are - * memory mapped interface base address, interface offset (see below) - * and clock identifier. - * - * stm32_get_gpio_bank_offset() returns a bank offset that is used to - * check DT configuration matches platform implementation of the banks - * description. - */ -unsigned int stm32_get_gpio_bank_offset(unsigned int bank); - /* Platform util for PMIC support */ bool stm32mp_with_pmic(void); diff --git a/core/arch/arm/plat-stm32mp2/conf.mk b/core/arch/arm/plat-stm32mp2/conf.mk new file mode 100644 index 0000000000000000000000000000000000000000..76dda579739873cdcad1851f08c613b2424a1303 --- /dev/null +++ b/core/arch/arm/plat-stm32mp2/conf.mk @@ -0,0 +1,61 @@ +flavor_dts_file-257F_EV1 = stm32mp257f-ev1.dts + +flavorlist-MP25 = $(flavor_dts_file-257F_EV1) + +ifneq ($(PLATFORM_FLAVOR),) +ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) +$(error Invalid platform flavor $(PLATFORM_FLAVOR)) +endif +CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) +endif +CFG_EMBED_DTB_SOURCE_FILE ?= stm32mp257f-ev1.dts + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP25)),) +$(call force,CFG_STM32MP25,y) +endif + +ifneq ($(CFG_STM32MP25),y) +$(error STM32 Platform must be defined) +endif + +include core/arch/arm/cpu/cortex-armv8-0.mk +supported-ta-targets ?= ta_arm64 + +$(call force,CFG_ARM64_core,y) +$(call force,CFG_DRIVERS_CLK,y) +$(call force,CFG_DRIVERS_CLK_DT,y) +$(call force,CFG_DRIVERS_GPIO,y) +$(call force,CFG_DRIVERS_PINCTRL,y) +$(call force,CFG_DT,y) +$(call force,CFG_GIC,y) +$(call force,CFG_HALT_CORES_ON_PANIC_SGI,15) +$(call force,CFG_INIT_CNTVOFF,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_WITH_LPAE,y) + +CFG_TZDRAM_START ?= 0x82000000 +CFG_TZDRAM_SIZE ?= 0x02000000 + +CFG_CORE_HEAP_SIZE ?= 262144 +CFG_CORE_RESERVED_SHM ?= n +CFG_DTB_MAX_SIZE ?= 262144 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_MMAP_REGIONS ?= 30 +CFG_NUM_THREADS ?= 5 +CFG_TEE_CORE_NB_CORE ?= 2 + +CFG_STM32_GPIO ?= y +CFG_STM32_UART ?= y + +# Default enable some test facitilites +CFG_WITH_STATS ?= y + +# Default disable ASLR +CFG_CORE_ASLR ?= n + +# UART instance used for early console (0 disables early console) +CFG_STM32_EARLY_CONSOLE_UART ?= 2 + +# Default disable external DT support +CFG_EXTERNAL_DT ?= n diff --git a/core/arch/arm/plat-stm32mp2/main.c b/core/arch/arm/plat-stm32mp2/main.c new file mode 100644 index 0000000000000000000000000000000000000000..81366e60d247c11049fe47505eb0d26fe8cc34e8 --- /dev/null +++ b/core/arch/arm/plat-stm32mp2/main.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include <config.h> +#include <console.h> +#include <drivers/gic.h> +#include <drivers/stm32_uart.h> +#include <initcall.h> +#include <kernel/boot.h> +#include <kernel/dt.h> +#include <kernel/interrupt.h> +#include <kernel/misc.h> +#include <kernel/spinlock.h> +#include <mm/core_memprot.h> +#include <platform_config.h> +#include <stm32_util.h> +#include <trace.h> + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB2_BASE, APB2_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB2_BASE, AHB2_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB3_BASE, AHB3_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAPB_BASE, SAPB_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAHB_BASE, SAHB_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); + +#define _ID2STR(id) (#id) +#define ID2STR(id) _ID2STR(id) + +static TEE_Result platform_banner(void) +{ + IMSG("Platform stm32mp2: flavor %s - DT %s", ID2STR(PLATFORM_FLAVOR), + ID2STR(CFG_EMBED_DTB_SOURCE_FILE)); + + return TEE_SUCCESS; +} + +service_init(platform_banner); + +/* + * Console + * + * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for + * trace console. Value 0 disables the early console. + * + * We cannot use the generic serial_console support since probing + * the console requires the platform clock driver to be already + * up and ready which is done only once service_init are completed. + */ +static struct stm32_uart_pdata console_data; + +void console_init(void) +{ +#ifdef CFG_STM32_UART + /* Early console initialization before MMU setup */ + struct uart { + paddr_t pa; + bool secure; + } uarts[] = { + [0] = { .pa = 0 }, + [1] = { .pa = USART1_BASE, .secure = true, }, + [2] = { .pa = USART2_BASE, .secure = false, }, + [3] = { .pa = USART3_BASE, .secure = false, }, + [4] = { .pa = UART4_BASE, .secure = false, }, + [5] = { .pa = UART5_BASE, .secure = false, }, + [6] = { .pa = USART6_BASE, .secure = false, }, + [7] = { .pa = UART7_BASE, .secure = false, }, + [8] = { .pa = UART8_BASE, .secure = false, }, + [9] = { .pa = UART9_BASE, .secure = false, }, + }; + + static_assert(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART); + + if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa) + return; + + /* No clock yet bound to the UART console */ + console_data.clock = NULL; + console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure; + stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa); + register_serial_console(&console_data.chip); + + IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART); +#endif +} + +#ifdef CFG_STM32_UART +static TEE_Result init_console_from_dt(void) +{ + struct stm32_uart_pdata *pd = NULL; + void *fdt = NULL; + int node = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + fdt = get_embedded_dt(); + res = get_console_node_from_dt(fdt, &node, NULL, NULL); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + fdt = get_external_dt(); + res = get_console_node_from_dt(fdt, &node, NULL, NULL); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + if (res != TEE_SUCCESS) + return res; + } + + pd = stm32_uart_init_from_dt_node(fdt, node); + if (!pd) { + IMSG("DTB disables console"); + register_serial_console(NULL); + return TEE_SUCCESS; + } + + /* Replace early console with the new one */ + console_flush(); + console_data = *pd; + register_serial_console(&console_data.chip); + IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-"); + free(pd); + + return TEE_SUCCESS; +} + +/* Probe console from DT once clock inits (service init level) are completed */ +service_init_late(init_console_from_dt); +#endif /*STM32_UART*/ + +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} diff --git a/core/arch/arm/plat-stm32mp2/platform_config.h b/core/arch/arm/plat-stm32mp2/platform_config.h new file mode 100644 index 0000000000000000000000000000000000000000..4d7af4a8c82b72f3a1dd6b6e5ae8c0bf8347cc1a --- /dev/null +++ b/core/arch/arm/plat-stm32mp2/platform_config.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include <mm/generic_ram_layout.h> + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 32 + +/* SoC interface registers base address ranges */ +#define APB1_BASE 0x40000000 +#define APB1_SIZE 0x00200000 +#define APB2_BASE 0x40200000 +#define APB2_SIZE 0x00040000 +#define AHB2_BASE 0x40400000 +#define AHB2_SIZE 0x01c00000 +#define AHB3_BASE 0x42000000 +#define AHB3_SIZE 0x02000000 +#define APB3_BASE 0x44000000 +#define APB3_SIZE 0x001f0000 +#define AHB4_BASE 0x44200000 +#define AHB4_SIZE 0x01e00000 +#define SAPB_BASE 0x46000000 +#define SAPB_SIZE 0x00200000 +#define SAHB_BASE 0x46200000 +#define SAHB_SIZE 0x01e00000 +#define APB4_BASE 0x48000000 +#define APB4_SIZE 0x00200000 +#define AHB5_BASE 0x48200000 +#define AHB5_SIZE 0x01e00000 + +/* SoC interface registers base address */ +#define UART2_BASE 0x400e0000 +#define UART3_BASE 0x400f0000 +#define UART4_BASE 0x40100000 +#define UART5_BASE 0x40110000 +#define I2C4_BASE 0x40150000 +#define I2C6_BASE 0x40170000 +#define UART6_BASE 0x40220000 +#define UART9_BASE 0x402c0000 +#define UART1_BASE 0x40330000 +#define SPI6_BASE 0x40350000 +#define UART7_BASE 0x40370000 +#define UART8_BASE 0x40380000 +#define OSPI1_BASE 0x40430000 +#define OSPI2_BASE 0x40440000 +#define HASH1_BASE 0x42010000 +#define RNG1_BASE 0x42020000 +#define CRYP1_BASE 0x42030000 +#define SAES_BASE 0x42050000 +#define PKA_BASE 0x42060000 +#define RIFSC_BASE 0x42080000 +#define RISAF5_BASE 0x420e0000 +#define RISAB6_BASE 0x42140000 +#define BSEC3_BASE 0x44000000 +#define IWDG2_BASE 0x44002000 +#define IWDG1_BASE 0x44010000 +#define RCC_BASE 0x44200000 +#define PWR_BASE 0x44210000 +#define SYSCFG_BASE 0x44230000 +#define GPIOA_BASE 0x44240000 +#define GPIOB_BASE 0x44250000 +#define GPIOC_BASE 0x44260000 +#define GPIOD_BASE 0x44270000 +#define GPIOE_BASE 0x44280000 +#define GPIOF_BASE 0x44290000 +#define GPIOG_BASE 0x442a0000 +#define GPIOH_BASE 0x442b0000 +#define GPIOI_BASE 0x442c0000 +#define GPIOJ_BASE 0x442d0000 +#define GPIOK_BASE 0x442e0000 +#define RTC_BASE 0x46000000 +#define TAMP_BASE 0x46010000 +#define GPIOZ_BASE 0x46200000 +#define STGEN_BASE 0x48080000 +#define FMC_BASE 0x48200000 +#define PCIE_BASE 0x48400000 +#define A35SSC_BASE 0x48800000 +#define GIC_BASE 0x4ac00000 +#define DDR_BASE UL(0x80000000) + +#define SYSRAM_BASE 0x0e000000 + +#define SRAM1_BASE 0x0e040000 + +/* GIC resources */ +#define GIC_SIZE 0x80000 +#define GICC_OFFSET 0x20000 +#define GICD_OFFSET 0x10000 + +/* Console configuration */ +#define GIC_SPI_UART4 126 + +#define TARGET_CPU0_GIC_MASK BIT(0) +#define TARGET_CPU1_GIC_MASK BIT(1) +#define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) + +/* USART/UART resources */ +#define USART1_BASE UART1_BASE +#define USART2_BASE UART2_BASE +#define USART3_BASE UART3_BASE +#define USART6_BASE UART6_BASE + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/core/arch/arm/plat-stm32mp2/stm32_util.h b/core/arch/arm/plat-stm32mp2/stm32_util.h new file mode 100644 index 0000000000000000000000000000000000000000..2575f0a5c1cf8a35980fde4fa9a283a6069a013c --- /dev/null +++ b/core/arch/arm/plat-stm32mp2/stm32_util.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef __STM32_UTIL_H__ +#define __STM32_UTIL_H__ + +#include <kernel/spinlock.h> +#include <stdint.h> +#include <types_ext.h> + +static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused) +{ +} + +static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base + __unused) { } + +static inline void stm32mp_register_gpioz_pin_count(size_t count __unused) { } + +#define may_spin_lock(lock) cpu_spin_lock_xsave(lock) +#define may_spin_unlock(lock, exceptions) cpu_spin_unlock_xrestore(lock, \ + exceptions) +#endif /*__STM32_UTIL_H__*/ diff --git a/core/arch/arm/plat-stm32mp2/sub.mk b/core/arch/arm/plat-stm32mp2/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..b5d5551e7f46aac78b063f67bd05d84f4980fcfd --- /dev/null +++ b/core/arch/arm/plat-stm32mp2/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . + +srcs-y += main.c diff --git a/core/arch/arm/plat-sunxi/main.c b/core/arch/arm/plat-sunxi/main.c index 7f4215a194f4973fd89970c6801051f5634f9f5d..b0f80484f218b43cab87818522d02b2cd0c8648a 100644 --- a/core/arch/arm/plat-sunxi/main.c +++ b/core/arch/arm/plat-sunxi/main.c @@ -130,7 +130,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } #endif diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c index d94aff33175610a11dafe8800a1dc02e7e655fe6..2ba622f1edce3ef7c1483620609321e0f88c01c2 100644 --- a/core/arch/arm/plat-synquacer/main.c +++ b/core/arch/arm/plat-synquacer/main.c @@ -59,8 +59,11 @@ static struct itr_handler timer_itr = { static TEE_Result init_timer_itr(void) { - itr_add(&timer_itr); - itr_enable(IT_SEC_TIMER); + if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &timer_itr)) + panic(); + + interrupt_enable(timer_itr.chip, timer_itr.it); /* Enable timer FIQ to fetch entropy required during boot */ generic_timer_start(TIMER_PERIOD_MS); diff --git a/core/arch/arm/plat-ti/main.c b/core/arch/arm/plat-ti/main.c index 9d9e75dd1f375d2ec30e47769a38cbd7dfb5970e..5b132ae7ec13bcb67b04364288471ff82425b924 100644 --- a/core/arch/arm/plat-ti/main.c +++ b/core/arch/arm/plat-ti/main.c @@ -41,7 +41,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } struct plat_nsec_ctx { diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk index 94a4e62742144b39a6f44578da0b82985ed650a0..eefe1e520393c3f50246be48e708b8597d24d842 100644 --- a/core/arch/arm/plat-vexpress/conf.mk +++ b/core/arch/arm/plat-vexpress/conf.mk @@ -63,7 +63,8 @@ $(call force,CFG_GIC,y) endif ifeq ($(PLATFORM_FLAVOR),fvp) -CFG_TEE_CORE_NB_CORE = 8 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_TEE_CORE_NB_CORE ?= 8 ifeq ($(CFG_CORE_SEL2_SPMC),y) CFG_TZDRAM_START ?= 0x06281000 CFG_TZDRAM_SIZE ?= 0x01D80000 @@ -76,13 +77,18 @@ CFG_SHMEM_SIZE ?= 0x00200000 # DRAM1 is defined above 4G $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) +CFG_AUTO_MAX_PA_BITS ?= y ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp) endif +ifeq ($(CFG_CORE_SEL1_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 9 +endif endif ifeq ($(PLATFORM_FLAVOR),juno) -CFG_TEE_CORE_NB_CORE = 6 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_TEE_CORE_NB_CORE ?= 6 CFG_TZDRAM_START ?= 0xff000000 CFG_TZDRAM_SIZE ?= 0x00ff8000 CFG_SHMEM_START ?= 0xfee00000 @@ -96,7 +102,8 @@ CFG_WITH_SOFTWARE_PRNG ?= n endif ifeq ($(PLATFORM_FLAVOR),qemu_virt) -CFG_TEE_CORE_NB_CORE = 4 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_TEE_CORE_NB_CORE ?= 4 # [0e00.0000 0e0f.ffff] is reserved to early boot CFG_TZDRAM_START ?= 0x0e100000 CFG_TZDRAM_SIZE ?= 0x00f00000 @@ -112,7 +119,7 @@ ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) # This is unfortunately currently not possible to do in make so we have to # calculate it offline, there's some asserts in # core/arch/arm/kernel/generic_boot.c to check that we got it right -CFG_ASAN_SHADOW_OFFSET = 0xc6a71c0 +CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0 endif $(call force,CFG_BOOT_SECONDARY_REQUEST,y) $(call force,CFG_PSCI_ARM32,y) @@ -123,7 +130,9 @@ CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 endif ifeq ($(PLATFORM_FLAVOR),qemu_armv8a) -CFG_TEE_CORE_NB_CORE = 4 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_TEE_CORE_NB_CORE ?= 4 +CFG_AUTO_MAX_PA_BITS ?= y ifneq ($(CFG_CORE_SEL2_SPMC),y) # [0e00.0000 0e0f.ffff] is reserved to early boot CFG_TZDRAM_START ?= 0x0e100000 @@ -136,7 +145,7 @@ CFG_SHMEM_SIZE ?= 0x00200000 CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) # See comment above -CFG_ASAN_SHADOW_OFFSET = 0xc6a71c0 +CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0 endif endif $(call force,CFG_DT,y) @@ -144,7 +153,14 @@ CFG_DTB_MAX_SIZE ?= 0x100000 ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp) endif + +CFG_CORE_ASYNC_NOTIF ?= y +ifeq ($(CFG_CORE_SEL1_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 8 +else ifneq ($(CFG_CORE_SEL2_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 endif +endif #PLATFORM_FLAVOR==qemu_armv8a ifneq (,$(filter $(PLATFORM_FLAVOR),qemu_virt qemu_armv8a)) CFG_DT_DRIVER_EMBEDDED_TEST ?= y diff --git a/core/arch/arm/plat-vexpress/main.c b/core/arch/arm/plat-vexpress/main.c index d2ab712d39b48705b68b8f50f954dd9a7888b257..63be30aa13839ac342ce315967dbfee063816752 100644 --- a/core/arch/arm/plat-vexpress/main.c +++ b/core/arch/arm/plat-vexpress/main.c @@ -1,10 +1,11 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2016-2023, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include <arm.h> +#include <config.h> #include <console.h> #include <drivers/gic.h> #include <drivers/hfic.h> @@ -19,6 +20,7 @@ #include <kernel/panic.h> #include <kernel/spinlock.h> #include <kernel/tee_time.h> +#include <kernel/thread_spmc.h> #include <mm/core_memprot.h> #include <mm/core_mmu.h> #include <platform_config.h> @@ -44,20 +46,34 @@ register_ddr(DRAM1_BASE, DRAM1_SIZE); #endif #ifdef CFG_GIC +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); -register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE); +#ifdef GIC_REDIST_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_REDIST_BASE, GIC_REDIST_SIZE); +#endif void boot_primary_init_intc(void) { +#ifdef GIC_REDIST_BASE + gic_init_v3(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET, + GIC_REDIST_BASE); +#else gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +#endif + if (IS_ENABLED(CFG_CORE_SEL1_SPMC) && + IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + size_t it = CFG_CORE_ASYNC_NOTIF_GIC_INTID; + + if (it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX) + gic_init_donate_sgi_to_ns(it); + thread_spmc_set_async_notif_intid(it); + } } -#if !defined(CFG_WITH_ARM_TRUSTED_FW) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } -#endif #endif /*CFG_GIC*/ #ifdef CFG_CORE_HAFNIUM_INTC @@ -101,14 +117,14 @@ static void read_console(void) } } -static enum itr_return console_itr_cb(struct itr_handler *h __maybe_unused) +static enum itr_return console_itr_cb(struct itr_handler *hdl) { if (notif_async_is_started()) { /* * Asynchronous notifications are enabled, lets read from * uart in the bottom half instead. */ - itr_disable(IT_CONSOLE_UART); + interrupt_disable(hdl->chip, hdl->it); notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF); } else { read_console(); @@ -136,11 +152,11 @@ static void yielding_console_notif(struct notif_driver *ndrv __unused, switch (ev) { case NOTIF_EVENT_DO_BOTTOM_HALF: read_console(); - itr_enable(IT_CONSOLE_UART); + interrupt_enable(console_itr.chip, console_itr.it); break; case NOTIF_EVENT_STOPPED: DMSG("Asynchronous notifications stopped"); - itr_enable(IT_CONSOLE_UART); + interrupt_enable(console_itr.chip, console_itr.it); break; default: EMSG("Unknown event %d", (int)ev); @@ -154,8 +170,15 @@ struct notif_driver console_notif = { static TEE_Result init_console_itr(void) { - itr_add(&console_itr); - itr_enable(IT_CONSOLE_UART); + TEE_Result res = TEE_ERROR_GENERIC; + + res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &console_itr); + if (res) + return res; + + interrupt_enable(console_itr.chip, console_itr.it); + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) notif_register_driver(&console_notif); return TEE_SUCCESS; diff --git a/core/arch/arm/plat-vexpress/platform_config.h b/core/arch/arm/plat-vexpress/platform_config.h index 206885c0f287d818aeb05d0949252c5a5c4c1cb6..21aa40acdcf7f6d6071098c6b6e06fec1e0fc6f7 100644 --- a/core/arch/arm/plat-vexpress/platform_config.h +++ b/core/arch/arm/plat-vexpress/platform_config.h @@ -96,6 +96,10 @@ #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x3000000 +#ifdef CFG_ARM_GICV3 +#define GIC_REDIST_BASE 0x2F100000 +#define GIC_REDIST_SIZE 0x00100000 +#endif #elif defined(PLATFORM_FLAVOR_juno) /* @@ -126,15 +130,17 @@ #define GICD_OFFSET 0 #define GICC_OFFSET 0x10000 +#ifdef CFG_ARM_GICV3 +#define GIC_REDIST_BASE 0x080A0000 +#define GIC_REDIST_SIZE 0x00F60000 +#endif #else #error "Unknown platform flavor" #endif -#ifdef GIC_BASE #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) -#endif #ifndef UART_BAUDRATE #define UART_BAUDRATE 115200 diff --git a/core/arch/arm/plat-zynq7k/main.c b/core/arch/arm/plat-zynq7k/main.c index 19f40c92f5e57a7da902c8de506d96b24e1e7e70..08af994fd03ce42ca1943f8a039df5601ea57bcf 100644 --- a/core/arch/arm/plat-zynq7k/main.c +++ b/core/arch/arm/plat-zynq7k/main.c @@ -148,7 +148,7 @@ void boot_primary_init_intc(void) void boot_secondary_init_intc(void) { - gic_cpu_init(); + gic_init_per_cpu(); } static vaddr_t slcr_access_range[] = { diff --git a/core/arch/riscv/include/kernel/misc_arch.h b/core/arch/riscv/include/kernel/misc_arch.h index 208e358f5fa1e51f4fbac4349a8aee15548baca3..c48c7d9a8f1b08c1b8fcefcf6ed94a70f9e8a5a9 100644 --- a/core/arch/riscv/include/kernel/misc_arch.h +++ b/core/arch/riscv/include/kernel/misc_arch.h @@ -3,7 +3,7 @@ * Copyright 2022 NXP */ -#ifndef KERNEL_MISC_ARCH_H -#define KERNEL_MISC_ARCH_H +#ifndef __KERNEL_MISC_ARCH_H +#define __KERNEL_MISC_ARCH_H -#endif /*KERNEL_MISC_ARCH_H*/ +#endif /*__KERNEL_MISC_ARCH_H*/ diff --git a/core/arch/riscv/include/kernel/tee_l2cc_mutex.h b/core/arch/riscv/include/kernel/tee_l2cc_mutex.h index 12b914780d64d714fadc5429aaf112d24e2a2854..9dc873a8ec24968a5c7f3da3277bfb66e37a0dda 100644 --- a/core/arch/riscv/include/kernel/tee_l2cc_mutex.h +++ b/core/arch/riscv/include/kernel/tee_l2cc_mutex.h @@ -2,7 +2,7 @@ /* * Copyright 2022 NXP */ -#ifndef TEE_L2CC_MUTEX_H -#define TEE_L2CC_MUTEX_H +#ifndef __KERNEL_TEE_L2CC_MUTEX_H +#define __KERNEL_TEE_L2CC_MUTEX_H -#endif /* TEE_L2CC_MUTEX_H */ +#endif /* __KERNEL_TEE_L2CC_MUTEX_H */ diff --git a/core/arch/riscv/include/kernel/thread_arch.h b/core/arch/riscv/include/kernel/thread_arch.h index e150fa10e86a5de25e32a9f268d53a78ad96ec50..1e2da17b726f8bf631cbe78a1a59d96ee4a0aeb5 100644 --- a/core/arch/riscv/include/kernel/thread_arch.h +++ b/core/arch/riscv/include/kernel/thread_arch.h @@ -32,6 +32,9 @@ struct thread_core_local { #ifdef CFG_CORE_DEBUG_CHECK_STACKS bool stackcheck_recursion; #endif +#ifdef CFG_FAULT_MITIGATION + struct ftmn_func_arg *ftmn_arg; +#endif } THREAD_CORE_LOCAL_ALIGNED; struct thread_user_vfp_state { diff --git a/core/arch/riscv/include/kernel/tlb_helpers.h b/core/arch/riscv/include/kernel/tlb_helpers.h index ad82024ab283bdcc9c5701641c55061ec8e4c2da..d81766b9d64d10c1a95469b853198c8b3ab384ba 100644 --- a/core/arch/riscv/include/kernel/tlb_helpers.h +++ b/core/arch/riscv/include/kernel/tlb_helpers.h @@ -3,8 +3,8 @@ * Copyright 2022 NXP */ -#ifndef TLB_HELPERS_H -#define TLB_HELPERS_H +#ifndef __KERNEL_TLB_HELPERS_H +#define __KERNEL_TLB_HELPERS_H #ifndef __ASSEMBLER__ @@ -15,4 +15,4 @@ void tlbi_va_asid(vaddr_t va, uint32_t asid); #endif /*!__ASSEMBLER__*/ -#endif /* TLB_HELPERS_H */ +#endif /* __KERNEL_TLB_HELPERS_H */ diff --git a/core/arch/riscv/include/mm/core_mmu_arch.h b/core/arch/riscv/include/mm/core_mmu_arch.h index 1284d47428361bfec40368d8b4bb1ad847f6bc5d..cc9aa798f2765b695d66635662f33e68ea7d6949 100644 --- a/core/arch/riscv/include/mm/core_mmu_arch.h +++ b/core/arch/riscv/include/mm/core_mmu_arch.h @@ -2,8 +2,8 @@ /* * Copyright 2022-2023 NXP */ -#ifndef __CORE_MMU_ARCH_H -#define __CORE_MMU_ARCH_H +#ifndef __MM_CORE_MMU_ARCH_H +#define __MM_CORE_MMU_ARCH_H #ifndef __ASSEMBLER__ #include <assert.h> @@ -150,4 +150,4 @@ static inline bool core_mmu_level_in_range(unsigned int level) } #endif /*__ASSEMBLER__*/ -#endif /* __CORE_MMU_ARCH_H */ +#endif /* __MM_CORE_MMU_ARCH_H */ diff --git a/core/arch/riscv/include/riscv.h b/core/arch/riscv/include/riscv.h index ecaba09b5b2225b89ff29364b431569e9b0db07d..59fb0c37c105aa635b1730f23ad358869cd23dae 100644 --- a/core/arch/riscv/include/riscv.h +++ b/core/arch/riscv/include/riscv.h @@ -3,8 +3,8 @@ * Copyright 2022-2023 NXP */ -#ifndef RISCV_H -#define RISCV_H +#ifndef __RISCV_H +#define __RISCV_H #include <compiler.h> #include <encoding.h> @@ -117,7 +117,7 @@ static inline __noprof void mb(void) static inline __noprof unsigned long read_tp(void) { - unsigned long tp; + unsigned long tp = 0; asm volatile("mv %0, tp" : "=&r"(tp)); return tp; @@ -389,4 +389,4 @@ static inline __noprof uint32_t read_cntfrq(void) #endif /*__ASSEMBLER__*/ -#endif /*RISCV_H*/ +#endif /*__RISCV_H*/ diff --git a/core/arch/riscv/include/sbi.h b/core/arch/riscv/include/sbi.h index 6ea6064d823d9130c9f2c138baf1c23ee4e7ceea..8b73edee938a6dca8f639c79cfc31c25c9e7d630 100644 --- a/core/arch/riscv/include/sbi.h +++ b/core/arch/riscv/include/sbi.h @@ -3,8 +3,8 @@ * Copyright 2022 NXP */ -#ifndef SBI_H -#define SBI_H +#ifndef __SBI_H +#define __SBI_H #if defined(CFG_RISCV_SBI) @@ -44,4 +44,4 @@ int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg); #endif /*__ASSEMBLER__*/ #endif /*defined(CFG_RISCV_SBI)*/ -#endif /*SBI_H*/ +#endif /*__SBI_H*/ diff --git a/core/arch/riscv/include/tee/entry_fast.h b/core/arch/riscv/include/tee/entry_fast.h index 08ca181f492202ec250ef42bdfb0ed20d80469a4..b3f1f81b77e5a16f9e0322886a569928c8233ae5 100644 --- a/core/arch/riscv/include/tee/entry_fast.h +++ b/core/arch/riscv/include/tee/entry_fast.h @@ -5,8 +5,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_ENTRY_FAST_H -#define TEE_ENTRY_FAST_H +#ifndef __TEE_ENTRY_FAST_H +#define __TEE_ENTRY_FAST_H #include <kernel/thread.h> @@ -31,4 +31,4 @@ size_t tee_entry_generic_get_api_call_count(void); void tee_entry_fast(struct thread_abi_args *args); void __tee_entry_fast(struct thread_abi_args *args); -#endif /* TEE_ENTRY_FAST_H */ +#endif /* __TEE_ENTRY_FAST_H */ diff --git a/core/arch/riscv/include/tee/optee_abi.h b/core/arch/riscv/include/tee/optee_abi.h index e65bebcac1a3a820d5d4094a4bc8742f2ab0d7e9..8528b34cac784d00a713c59edfd26c94c6b1eba1 100644 --- a/core/arch/riscv/include/tee/optee_abi.h +++ b/core/arch/riscv/include/tee/optee_abi.h @@ -3,8 +3,8 @@ * Copyright 2023 NXP * Copyright (c) 2015-2021, Linaro Limited */ -#ifndef OPTEE_ABI_H -#define OPTEE_ABI_H +#ifndef __TEE_OPTEE_ABI_H +#define __TEE_OPTEE_ABI_H #include <stdint.h> @@ -702,4 +702,4 @@ ((((ret) & OPTEE_ABI_RETURN_RPC_PREFIX_MASK) == \ OPTEE_ABI_RETURN_RPC_PREFIX))); }) -#endif /* OPTEE_ABI_H */ +#endif /* __TEE_OPTEE_ABI_H */ diff --git a/core/arch/riscv/include/tee/teeabi_opteed.h b/core/arch/riscv/include/tee/teeabi_opteed.h index 50f846548bdf840e3e509a16488d8a3ac0e4cb4c..05c6aabb8d77a91940b818755305cbc481b2da2e 100644 --- a/core/arch/riscv/include/tee/teeabi_opteed.h +++ b/core/arch/riscv/include/tee/teeabi_opteed.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEEABI_OPTEED_H -#define TEEABI_OPTEED_H +#ifndef __TEE_TEEABI_OPTEED_H +#define __TEE_TEEABI_OPTEED_H /* * This file specify ABI function IDs used when returning from TEE to the @@ -108,4 +108,4 @@ #define TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) -#endif /*TEEABI_OPTEED_H*/ +#endif /*__TEE_TEEABI_OPTEED_H*/ diff --git a/core/arch/riscv/include/tee/teeabi_opteed_macros.h b/core/arch/riscv/include/tee/teeabi_opteed_macros.h index 6345bd613a659f181d487b999dbcc0a00a85348c..911821d5b1fbe4c0f203271dd9d67ff241d0476f 100644 --- a/core/arch/riscv/include/tee/teeabi_opteed_macros.h +++ b/core/arch/riscv/include/tee/teeabi_opteed_macros.h @@ -4,11 +4,11 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEEABI_OPTEED_MACROS_H -#define TEEABI_OPTEED_MACROS_H +#ifndef __TEE_TEEABI_OPTEED_MACROS_H +#define __TEE_TEEABI_OPTEED_MACROS_H #define TEEABI_OPTEED_RV(func_num) \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED, (func_num)) -#endif /*TEEABI_OPTEED_MACROS_H*/ +#endif /*__TEE_TEEABI_OPTEED_MACROS_H*/ diff --git a/core/arch/riscv/kernel/boot.c b/core/arch/riscv/kernel/boot.c index 16c424cefa4d5676ab002e5cefb920596d156062..6530a8b5cb7d5d9120d7a2d3b5ecea5a0138a389 100644 --- a/core/arch/riscv/kernel/boot.c +++ b/core/arch/riscv/kernel/boot.c @@ -124,8 +124,7 @@ __weak void boot_secondary_init_intc(void) { } -void boot_init_primary_early(unsigned long pageable_part __unused, - unsigned long nsec_entry __unused) +void boot_init_primary_early(void) { unsigned long e = PADDR_INVALID; @@ -135,11 +134,11 @@ void boot_init_primary_early(unsigned long pageable_part __unused, void boot_init_primary_late(unsigned long fdt, unsigned long tos_fw_config __unused) { - init_external_dt(fdt); + init_external_dt(fdt, CFG_DTB_MAX_SIZE); update_external_dt(); IMSG("OP-TEE version: %s", core_v_str); - if (IS_ENABLED(CFG_WARN_INSECURE)) { + if (IS_ENABLED(CFG_INSECURE)) { IMSG("WARNING: This OP-TEE configuration might be insecure!"); IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); } diff --git a/core/arch/riscv/kernel/thread_arch.c b/core/arch/riscv/kernel/thread_arch.c index 9f40ad4e3461dbb887bc1596b692d58adebe4d6e..38299a6138411b89dab45313242539a80a21adf4 100644 --- a/core/arch/riscv/kernel/thread_arch.c +++ b/core/arch/riscv/kernel/thread_arch.c @@ -14,6 +14,7 @@ #include <keep.h> #include <kernel/asan.h> #include <kernel/boot.h> +#include <kernel/interrupt.h> #include <kernel/linker.h> #include <kernel/lockdep.h> #include <kernel/misc.h> diff --git a/core/arch/riscv/plat-spike/conf.mk b/core/arch/riscv/plat-spike/conf.mk index 27108ac696fdbff6bf052c25264b6bd0c59849c5..2047341dbb59ad1a27d2408c3e514356d341fb44 100644 --- a/core/arch/riscv/plat-spike/conf.mk +++ b/core/arch/riscv/plat-spike/conf.mk @@ -67,7 +67,7 @@ $(call force,CFG_SECSTOR_TA,n) $(call force,CFG_SHOW_CONF_ON_BOOT,n) $(call force,CFG_SYSCALL_WRAPPERS_MCOUNT,n) $(call force,CFG_BOOT_SYNC_CPU,y) -$(call force,CFG_WARN_INSECURE,y) +$(call force,CFG_INSECURE,y) $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) CFG_RISCV_MTIME_RATE ?= 10000000 CFG_TDDRAM_START ?= 0xbdb00000 diff --git a/core/arch/riscv/plat-virt/conf.mk b/core/arch/riscv/plat-virt/conf.mk index 98b703f6cbed8c45a6d10737e1959f9832a2d580..15bc09267947a4ad84f40dc2ad144c2c46d58518 100644 --- a/core/arch/riscv/plat-virt/conf.mk +++ b/core/arch/riscv/plat-virt/conf.mk @@ -4,6 +4,8 @@ $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_TEE_CORE_DEBUG,n) $(call force,CFG_CORE_DYN_SHM,n) +CFG_DT ?= y + # Crypto flags $(call force,CFG_WITH_SOFTWARE_PRNG,y) @@ -13,18 +15,21 @@ $(call force,CFG_WITH_STACK_CANARIES,n) $(call force,CFG_CORE_SANITIZE_KADDRESS,n) # Hart-related flags -$(call force,CFG_TEE_CORE_NB_CORE,1) -$(call force,CFG_NUM_THREADS,1) +CFG_TEE_CORE_NB_CORE ?= 1 +CFG_NUM_THREADS ?= 1 $(call force,CFG_BOOT_SYNC_CPU,y) # RISC-V-specific flags rv64-platform-isa ?= rv64imafdc_zicsr_zifencei +$(call force,CFG_RISCV_M_MODE,n) +$(call force,CFG_RISCV_S_MODE,y) $(call force,CFG_RISCV_PLIC,y) $(call force,CFG_SBI_CONSOLE,n) $(call force,CFG_16550_UART,y) $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) CFG_RISCV_MTIME_RATE ?= 10000000 +CFG_RISCV_SBI ?= y # TA-related flags supported-ta-targets = ta_rv64 diff --git a/core/core.mk b/core/core.mk index b023e46ac43ecfe384becfdceeaed7ac7879f95b..71c4699860a6d19a213b051defc760320f06aea4 100644 --- a/core/core.mk +++ b/core/core.mk @@ -15,6 +15,7 @@ PLATFORM_$(PLATFORM) := y PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y $(eval $(call cfg-depends-all,CFG_PAGED_USER_TA,CFG_WITH_PAGER CFG_WITH_USER_TA)) +_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL ?= $(CFG_CORE_ASYNC_NOTIF) include core/crypto.mk ifeq ($(CFG_SCMI_SCPFW),y) diff --git a/core/crypto/cbc-mac.c b/core/crypto/cbc-mac.c index c38b0581d146cf4cc035d3673bb4428863a0c3df..7fdcecd832827c8d7dd49dfdca218929a1c955ce 100644 --- a/core/crypto/cbc-mac.c +++ b/core/crypto/cbc-mac.c @@ -83,7 +83,7 @@ static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx, nblocks = MIN(len / mc->block_len, (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); if (nblocks > 1) - out_tmp = malloc(nblocks * mc->block_len); + out_tmp = calloc(nblocks, mc->block_len); while (len >= mc->block_len) { nblocks = MIN(len / mc->block_len, diff --git a/core/crypto/sm3.c b/core/crypto/sm3.c index 26bba100364fd025737a96bd9697c5484e87389a..b0d9a8e49db2e3d375efd6aef83dc773ec2cae73 100644 --- a/core/crypto/sm3.c +++ b/core/crypto/sm3.c @@ -50,6 +50,20 @@ void sm3_init(struct sm3_context *ctx) ctx->state[7] = 0xB0FB0E4E; } +#define SHL(x, n) ((x) << (n)) + +static uint32_t rotl(uint32_t val, int shift) +{ + shift &= 0x1F; + + if (shift == 0) + return val; + + return SHL(val, shift) | (val >> (32 - shift)); +} + +#define ROTL(x, n) rotl((x), (n)) + static void __maybe_unused sm3_process(struct sm3_context *ctx, const uint8_t data[64]) { @@ -87,9 +101,6 @@ static void __maybe_unused sm3_process(struct sm3_context *ctx, #define GG0(x, y, z) ((x) ^ (y) ^ (z)) #define GG1(x, y, z) (((x) & (y)) | ((~(x)) & (z))) -#define SHL(x, n) ((x) << (n)) -#define ROTL(x, n) (SHL((x), (n) & 0x1F) | ((x) >> (32 - ((n) & 0x1F)))) - #define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17)) #define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23)) diff --git a/core/drivers/atmel_piobu.c b/core/drivers/atmel_piobu.c index 1f6aa115f8f4e04815bdddda37f79867d9f5cb54..df06620a616ca521fd0ab859174012d0ea5df002 100644 --- a/core/drivers/atmel_piobu.c +++ b/core/drivers/atmel_piobu.c @@ -13,6 +13,7 @@ #include <kernel/boot.h> #include <kernel/dt.h> #include <kernel/dt_driver.h> +#include <kernel/interrupt.h> #include <kernel/pm.h> #include <libfdt.h> #include <mm/core_memprot.h> @@ -267,8 +268,16 @@ static struct itr_handler secumod_itr_handler = { static void secumod_interrupt_init(void) { - itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); - itr_enable(secumod_itr_handler.it); + TEE_Result res = TEE_ERROR_GENERIC; + + secumod_itr_handler.chip = interrupt_get_main_chip(); + + res = interrupt_add_configure_handler(&secumod_itr_handler, + IRQ_TYPE_LEVEL_HIGH, 7); + if (res) + panic(); + + interrupt_enable(secumod_itr_handler.chip, secumod_itr_handler.it); } static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) diff --git a/core/drivers/atmel_saic.c b/core/drivers/atmel_saic.c index 5989056ffda314b791de7689dfe193e040b8f879..32aa8676a1a9121907362596c377799c5374b0a1 100644 --- a/core/drivers/atmel_saic.c +++ b/core/drivers/atmel_saic.c @@ -269,7 +269,7 @@ TEE_Result atmel_saic_setup(void) ret = dt_map_dev(fdt, node, &saic.base, &size, DT_MAP_AUTO); if (ret) { - EMSG("Failed to map SAIC\n"); + EMSG("Failed to map SAIC"); return TEE_ERROR_GENERIC; } diff --git a/core/drivers/atmel_wdt.c b/core/drivers/atmel_wdt.c index b2aa5458d176a8cc4fbcb1dbde678111783e037e..9f1aa3047052b4172282b83fc42b69cc0e24e6be 100644 --- a/core/drivers/atmel_wdt.c +++ b/core/drivers/atmel_wdt.c @@ -11,8 +11,10 @@ #include <kernel/delay.h> #include <kernel/dt.h> #include <kernel/dt_driver.h> +#include <kernel/interrupt.h> #include <kernel/pm.h> #include <matrix.h> +#include <mm/core_mmu.h> #include <sama5d2.h> #include <tee_api_types.h> @@ -229,7 +231,8 @@ static TEE_Result wdt_node_probe(const void *fdt, int node, uint32_t irq_type = 0; uint32_t irq_prio = 0; int it = DT_INFO_INVALID_INTERRUPT; - struct itr_handler *it_hdlr; + struct itr_handler *it_hdlr = NULL; + TEE_Result res = TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_PARAMETERS; @@ -244,28 +247,37 @@ static TEE_Result wdt_node_probe(const void *fdt, int node, it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio); if (it == DT_INFO_INVALID_INTERRUPT) - goto err_free_wdt; + goto err_free; - it_hdlr = itr_alloc_add_type_prio(it, &atmel_wdt_itr_cb, 0, wdt, - irq_type, irq_prio); - if (!it_hdlr) - goto err_free_wdt; + res = interrupt_alloc_add_conf_handler(interrupt_get_main_chip(), + it, atmel_wdt_itr_cb, 0, wdt, + irq_type, irq_prio, &it_hdlr); + if (res) + goto err_free; if (dt_map_dev(fdt, node, &wdt->base, &size, DT_MAP_AUTO) < 0) - goto err_free_itr_handler; + goto err_remove_handler; /* Get current state of the watchdog */ wdt->mr = io_read32(wdt->base + WDT_MR) & WDT_MR_WDDIS; atmel_wdt_init_hw(wdt); - itr_enable(it); + interrupt_enable(it_hdlr->chip, it_hdlr->it); + + res = watchdog_register(&wdt->chip); + if (res) + goto err_disable_unmap; + atmel_wdt_register_pm(wdt); - return watchdog_register(&wdt->chip); + return TEE_SUCCESS; -err_free_itr_handler: - itr_free(it_hdlr); -err_free_wdt: +err_disable_unmap: + interrupt_disable(it_hdlr->chip, it_hdlr->it); + core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)wdt->base, size); +err_remove_handler: + interrupt_remove_free_handler(it_hdlr); +err_free: free(wdt); return TEE_ERROR_GENERIC; diff --git a/core/drivers/bcm_hwrng.c b/core/drivers/bcm_hwrng.c index d9351c1c1a6fa6e20ee3c2dae6493b2ea45c3c3a..96e3097c38baeabb630237b1a25890d38f54ccad 100644 --- a/core/drivers/bcm_hwrng.c +++ b/core/drivers/bcm_hwrng.c @@ -76,7 +76,7 @@ static TEE_Result bcm_hwrng_init(void) bcm_hwrng_reset(); - DMSG("bcm_hwrng init done\n"); + DMSG("bcm_hwrng init done"); return TEE_SUCCESS; } diff --git a/core/drivers/clk/clk.c b/core/drivers/clk/clk.c index 00cb57e267884f5cdb2bbec408fd751e187f7129..8f5a6a5d28b22c86a50af8816548f978eef79e5c 100644 --- a/core/drivers/clk/clk.c +++ b/core/drivers/clk/clk.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Bootlin + * Copyright (c) 2023, STMicroelectronics */ +#include <config.h> #include <drivers/clk.h> #include <kernel/boot.h> #include <kernel/panic.h> @@ -10,10 +12,15 @@ #include <libfdt.h> #include <malloc.h> #include <stddef.h> +#include <stdio.h> /* Global clock tree lock */ static unsigned int clk_lock = SPINLOCK_UNLOCK; +#ifdef CFG_DRIVERS_CLK_PRINT_TREE +static SLIST_HEAD(, clk) clock_list = SLIST_HEAD_INITIALIZER(clock_list); +#endif + struct clk *clk_alloc(const char *name, const struct clk_ops *ops, struct clk **parent_clks, size_t parent_count) { @@ -42,7 +49,7 @@ void clk_free(struct clk *clk) static bool __maybe_unused clk_check(struct clk *clk) { - if (!clk->ops) + if (!clk || !clk->ops) return false; if (clk->ops->set_parent && !clk->ops->get_parent) @@ -101,6 +108,10 @@ TEE_Result clk_register(struct clk *clk) clk_init_parent(clk); clk_compute_rate_no_lock(clk); +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + SLIST_INSERT_HEAD(&clock_list, clk, link); +#endif + DMSG("Registered clock %s, freq %lu", clk->name, clk_get_rate(clk)); return TEE_SUCCESS; @@ -310,3 +321,169 @@ TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, return clk->ops->get_rates_array(clk, start_index, rates, nb_elts); } + +/* Return updated message buffer position of NULL on failure */ +static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) +{ + va_list ap = { }; + int max_len = end - cur; + int ret = 0; + + va_start(ap, fmt); + ret = vsnprintf(cur, max_len, fmt, ap); + va_end(ap); + + if (ret < 0 || ret >= max_len) + return NULL; + + return cur + ret; +} + +static struct clk *find_next_clk(struct clk *parent __maybe_unused, + struct clk *sibling __maybe_unused) +{ + struct clk *clk = NULL; + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + if (sibling) + clk = SLIST_NEXT(sibling, link); + else + clk = SLIST_FIRST(&clock_list); + + while (clk && clk->parent != parent) + clk = SLIST_NEXT(clk, link); +#endif + + return clk; +} + +static bool clk_is_parent_last_child(struct clk *clk) +{ + return !find_next_clk(clk->parent, clk); +} + +static bool indent_last_node_already_found(struct clk *node_clk, + int node_indent, int cur_indent) +{ + struct clk *clk = node_clk; + int n = 0; + + /* Find parent clock at level @node_indent - @cur_indent - 1 */ + for (n = 0; n < node_indent - cur_indent - 1; n++) + clk = clk->parent; + + return clk_is_parent_last_child(clk); +} + +static void __maybe_unused print_clk(struct clk *clk, int indent) +{ + static const char * const rate_unit[] = { "Hz", "kHz", "MHz", "GHz" }; + int max_unit = ARRAY_SIZE(rate_unit); + unsigned long rate = 0; + char msg_buf[128] = { }; + char *msg_end = msg_buf + sizeof(msg_buf); + char *msg = msg_buf; + int n = 0; + + /* + * Currently prints the clock state based on the clock refcount. + * A future change could print the hardware clock state when + * related clock driver provides a struct clk_ops::is_enabled handler + */ + + if (indent) { + /* Indent for root clock level */ + msg = add_msg(msg, msg_end, " "); + if (!msg) + goto out; + + /* Indent for root parent to clock parent levels */ + for (n = 0; n < indent - 1; n++) { + if (indent_last_node_already_found(clk, indent, n)) + msg = add_msg(msg, msg_end, " "); + else + msg = add_msg(msg, msg_end, "| "); + + if (!msg) + goto out; + } + + /* Clock indentation */ + if (clk_is_parent_last_child(clk)) + msg = add_msg(msg, msg_end, "`-- "); + else + msg = add_msg(msg, msg_end, "|-- "); + } else { + /* Root clock indentation */ + msg = add_msg(msg, msg_end, "o- "); + } + if (!msg) + goto out; + + rate = clk_get_rate(clk); + for (n = 1; rate && !(rate % 1000) && n < max_unit; n++) + rate /= 1000; + + msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / %ld %s)", + clk_get_name(clk), + refcount_val(&clk->enabled_count) ? "on " : "off", + refcount_val(&clk->enabled_count), + rate, rate_unit[n - 1]); + if (!msg) + goto out; + +out: + if (!msg) + snprintf(msg_end - 4, 4, "..."); + + DMSG("%s", msg_buf); +} + +static void print_tree(void) +{ + struct clk *clk = NULL; + struct clk *parent = NULL; + struct clk *next = NULL; + int indent = -1; + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + if (SLIST_EMPTY(&clock_list)) { + DMSG("-- No registered clock"); + return; + } +#endif + + while (true) { + next = find_next_clk(parent, clk); + if (next) { + print_clk(next, indent + 1); + /* Enter the subtree of the next clock */ + parent = next; + indent++; + clk = NULL; + } else { + /* + * We've processed all children at this level. + * If parent is NULL we're at the top and are done. + */ + if (!parent) + break; + /* + * Move up one level to resume with the next + * child clock of the parent. + */ + clk = parent; + parent = clk->parent; + indent--; + } + } +} + +void clk_print_tree(void) +{ + if (IS_ENABLED(CFG_DRIVERS_CLK_PRINT_TREE) && + TRACE_LEVEL >= TRACE_DEBUG) { + DMSG("Clock tree summary (informative):"); + print_tree(); + } +} diff --git a/core/drivers/crypto/caam/acipher/caam_dsa.c b/core/drivers/crypto/caam/acipher/caam_dsa.c index d60bb8e89e3b2ff537fc8b3d3b506ff53e294db3..8c0dbf055e213ac7da0c410b177c67db1533d069 100644 --- a/core/drivers/crypto/caam/acipher/caam_dsa.c +++ b/core/drivers/crypto/caam/acipher/caam_dsa.c @@ -579,7 +579,7 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes, /* Message length */ caam_desc_add_word(desc, sdata->message.length); - caam_desc_add_word(desc, DSA_SIGN(DL)); + caam_desc_add_word(desc, DSA_SIGN(DL, HASHED)); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); @@ -721,7 +721,7 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata, size_t l_bytes, /* Message length */ caam_desc_add_word(desc, sdata->message.length); - caam_desc_add_word(desc, DSA_VERIFY(DL)); + caam_desc_add_word(desc, DSA_VERIFY(DL, HASHED)); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); diff --git a/core/drivers/crypto/caam/acipher/caam_ecc.c b/core/drivers/crypto/caam/acipher/caam_ecc.c index 62c113c409f4639995ded2f683c6fc8e1636e45b..b9c2cde8817dc64f9ce667718c8dc7b32cf957f4 100644 --- a/core/drivers/crypto/caam/acipher/caam_ecc.c +++ b/core/drivers/crypto/caam/acipher/caam_ecc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright 2018-2021 NXP + * Copyright 2018-2021, 2024 NXP * * Implementation of ECC functions */ @@ -322,6 +322,63 @@ out: return ret; } +/* + * Check if MES_REP to be sent in descriptor is 00. + * Only required in case message length and key size is more than 40bytes + * because of limitation of Class 2 context register size on i.MX8M series. + * Example case below: + * When we try to do signature with P384-SHA384, in this case the key size + * will be 48bytes and Message size will also be 48bytes. + * This will work only when we set MES_REP = 0 in descriptor, + * but in this case, we don't need the padding to be done on the message. + * + * @msg_length: Message Length in bytes + * @key_size: Key size in bytes + */ +static bool msg_mes_rep(size_t msg_length, size_t key_size) +{ + return IS_ENABLED(CFG_NXP_CAAM_C2_CTX_REG_WA) && msg_length > 40 && + key_size > 40; +} + +/* + * Check if padding is required on message to make it of same length + * as that of key size. + * Only required in case message length and key size is more than 40bytes + * because of limitation of Class 2 context register size on i.MX8M series. + * So this will be applicable on P384 and P521 ECC curves because these + * curves have key_size more than 40bytes. + * + * @msg_length: Message Length in bytes + * @key_size: Key size in bytes + */ +static bool padding_required(size_t msg_length, size_t key_size) +{ + return msg_mes_rep(msg_length, key_size) && msg_length < key_size; +} + +/* + * Add padding of 00s in start of message + * + * @buf: Buffer in which padded message will be placed. + * @data: Original message + * @msg_length: Message Length in bytes + * @key_size: Key Size in bytes + */ +static TEE_Result add_padding(struct caambuf *buf, uint8_t *data, + size_t msg_length, size_t key_size) +{ + enum caam_status retstatus = CAAM_FAILURE; + + retstatus = caam_calloc_align_buf(buf, key_size); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + memcpy(buf->data + key_size - msg_length, data, msg_length); + + return TEE_SUCCESS; +} + /* * Signature of ECC message * Note the message to sign is already hashed @@ -343,6 +400,7 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; + struct caambuf caambuf_msg = { }; ECC_TRACE("ECC Signature"); @@ -365,19 +423,35 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) goto out; } - /* Prepare the input message CAAM Descriptor entry */ - ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, - sdata->message.length); - if (ret) - goto out; + ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); + + if (padding_required(sdata->message.length, sdata->size_sec)) { + ret = add_padding(&caambuf_msg, sdata->message.data, + sdata->message.length, sdata->size_sec); + if (ret) + goto out; + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, + caambuf_msg.length); + if (ret) + goto out; + + ECC_DUMPBUF("Padded Message", caambuf_msg.data, + caambuf_msg.length); + } else { + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + } if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG; caam_dmaobj_cache_push(&msg); - ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); - /* * ReAllocate the signature result buffer with a maximum size * of the roundup to 16 bytes of the secure size in bytes if @@ -420,10 +494,15 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); /* Signature 2nd part */ caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); - /* Message length */ - caam_desc_add_word(desc, sdata->message.length); - caam_desc_add_word(desc, DSA_SIGN(ECC)); + if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { + caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP)); + } else { + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED)); + } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); @@ -452,6 +531,7 @@ out: caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_d); caam_dmaobj_free(&sign_c); + caam_free_buf(&caambuf_msg); return ret; } @@ -477,6 +557,7 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; + struct caambuf caambuf_msg = { }; ECC_TRACE("ECC Verify"); @@ -499,11 +580,24 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) goto out; } - /* Prepare the input message CAAM Descriptor entry */ - ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, - sdata->message.length); - if (ret) - goto out; + if (padding_required(sdata->message.length, sdata->size_sec)) { + ret = add_padding(&caambuf_msg, sdata->message.data, + sdata->message.length, sdata->size_sec); + if (ret) + goto out; + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, + caambuf_msg.length); + if (ret) + goto out; + } else { + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + } if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG; @@ -556,10 +650,16 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); /* Temporary buffer */ caam_desc_add_ptr(desc, tmp.paddr); - /* Message length */ - caam_desc_add_word(desc, sdata->message.length); - caam_desc_add_word(desc, DSA_VERIFY(ECC)); + if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { + caam_desc_add_word(desc, DSA_VERIFY(ECC, MES_REP)); + } else { + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_VERIFY(ECC, HASHED)); + } + desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); @@ -587,6 +687,7 @@ out: caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_c); caam_dmaobj_free(&sign_d); + caam_free_buf(&caambuf_msg); return ret; } diff --git a/core/drivers/crypto/caam/caam_jr.c b/core/drivers/crypto/caam/caam_jr.c index eeb64f02f8fe4b7481b2095d2bd84925733a7d99..a3bf68a329e5d14defc07b59335b9a5fc231717d 100644 --- a/core/drivers/crypto/caam/caam_jr.c +++ b/core/drivers/crypto/caam/caam_jr.c @@ -159,7 +159,7 @@ end_alloc: static enum itr_return caam_jr_irqhandler(struct itr_handler *handler) { JR_TRACE("Disable the interrupt"); - itr_disable(handler->it); + interrupt_disable(handler->chip, handler->it); /* Send a signal to exit WFE loop */ sev(); @@ -582,13 +582,17 @@ enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg) * Prepare the interrupt handler to secure the interrupt even * if the interrupt is not used */ + jr_privdata->it_handler.chip = interrupt_get_main_chip(); jr_privdata->it_handler.it = jrcfg->it_num; jr_privdata->it_handler.flags = ITRF_TRIGGER_LEVEL; jr_privdata->it_handler.handler = caam_jr_irqhandler; jr_privdata->it_handler.data = jr_privdata; #if defined(CFG_NXP_CAAM_RUNTIME_JR) && defined(CFG_CAAM_ITR) - itr_add(&jr_privdata->it_handler); + if (interrupt_add_handler(&jr_privdata->it_handler)) { + retstatus = CAAM_FAILURE; + goto end_init; + } #endif caam_hal_jr_enable_itr(jr_privdata->baseaddr); diff --git a/core/drivers/crypto/caam/caam_rng.c b/core/drivers/crypto/caam/caam_rng.c index fa81c222f38bd673a163e3c5eb42bf4ed8fb2eac..a2a8fdd71e945001bc5c00beb31c7a680ccb6eb9 100644 --- a/core/drivers/crypto/caam/caam_rng.c +++ b/core/drivers/crypto/caam/caam_rng.c @@ -60,6 +60,7 @@ struct rngdata { struct rng_privdata { vaddr_t baseaddr; /* RNG base address */ bool instantiated; /* RNG instantiated */ + bool pr_enabled; /* RNG prediction resistance */ struct rngdata databuf[RNG_DATABUF_NB]; /* RNG Data generation */ uint8_t dataidx; /* Current RNG Data buffer */ }; @@ -158,6 +159,10 @@ static enum caam_status prepare_gen_desc(struct rngdata *rng) { paddr_t paddr = 0; uint32_t *desc = NULL; + uint32_t op = RNG_GEN_DATA; + + if (rng_privdata->pr_enabled) + op |= ALGO_RNG_PR; /* Convert the buffer virtual address to physical address */ paddr = virt_to_phys(rng->data); @@ -168,7 +173,7 @@ static enum caam_status prepare_gen_desc(struct rngdata *rng) caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); - caam_desc_add_word(desc, RNG_GEN_DATA); + caam_desc_add_word(desc, op); caam_desc_add_word(desc, FIFO_ST(RNG_TO_MEM, rng->size)); caam_desc_add_ptr(desc, paddr); @@ -523,8 +528,14 @@ enum caam_status caam_rng_instantiation(void) } while (retstatus == CAAM_NO_ERROR); end_inst: - if (retstatus == CAAM_NO_ERROR) + if (retstatus == CAAM_NO_ERROR) { rng_privdata->instantiated = true; + rng_privdata->pr_enabled = + caam_hal_rng_pr_enabled(rng_privdata->baseaddr); + + RNG_TRACE("RNG prediction resistance is %sabled", + rng_privdata->pr_enabled ? "en" : "dis"); + } caam_free_desc(&desc); @@ -556,6 +567,27 @@ enum caam_status caam_rng_init(vaddr_t ctrl_addr) } #ifdef CFG_NXP_CAAM_RNG_DRV +#ifdef CFG_WITH_SOFTWARE_PRNG +void plat_rng_init(void) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t buf[64] = { }; + + res = do_rng_read(buf, sizeof(buf)); + if (res) { + EMSG("Failed to read RNG: %#" PRIx32, res); + panic(); + } + + res = crypto_rng_init(buf, sizeof(buf)); + if (res) { + EMSG("Failed to initialize RNG: %#" PRIx32, res); + panic(); + } + + RNG_TRACE("PRNG seeded from CAAM"); +} +#else /* !CFG_WITH_SOFTWARE_PRNG */ TEE_Result hw_get_random_bytes(void *buf, size_t blen) { if (!buf) @@ -567,4 +599,5 @@ TEE_Result hw_get_random_bytes(void *buf, size_t blen) void plat_rng_init(void) { } -#endif +#endif /* CFG_WITH_SOFTWARE_PRNG */ +#endif /* CFG_NXP_CAAM_RNG_DRV */ diff --git a/core/drivers/crypto/caam/crypto.mk b/core/drivers/crypto/caam/crypto.mk index 8483680fd164fae798fc454da767a58253647f56..13f8e4cc070e93b079829dd799f3e4e60a8d5770 100644 --- a/core/drivers/crypto/caam/crypto.mk +++ b/core/drivers/crypto/caam/crypto.mk @@ -71,8 +71,8 @@ caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist))) $(call force, CFG_CAAM_SIZE_ALIGN,4) $(call force, CFG_JR_BLOCK_SIZE,0x10000) -$(call force, CFG_JR_INDEX,2) -$(call force, CFG_JR_INT,355) +$(call force, CFG_JR_INDEX,3) +$(call force, CFG_JR_INT,356) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_CAAM_JR_DISABLE_NODE,n) caam-crypto-drivers += RSA DSA ECC DH MATH @@ -83,6 +83,11 @@ $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT,146) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_JR_HAB_INDEX,0) +# There is a limitation on i.MX8M platforms regarding ECDSA Sign/Verify +# Size of Class 2 Context register is 40bytes, because of which sign/verify +# of a hash of more than 40bytes fails. So a workaround is implemented for +# this issue, controlled by CFG_NXP_CAAM_C2_CTX_REG_WA flag. +$(call force, CFG_NXP_CAAM_C2_CTX_REG_WA,y) caam-drivers += MP DEK caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist))) @@ -143,9 +148,9 @@ CFG_CAAM_JR_DISABLE_NODE ?= y # Enable CAAM non-crypto drivers $(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) -# Disable software RNG if CAAM RNG driver is enabled +# Prefer CAAM HWRNG over PRNG seeded by CAAM ifeq ($(CFG_NXP_CAAM_RNG_DRV), y) -$(call force, CFG_WITH_SOFTWARE_PRNG,n,Mandated by CFG_NXP_CAAM_RNG_DRV) +CFG_WITH_SOFTWARE_PRNG ?= n endif # DEK driver requires the SM driver to be enabled diff --git a/core/drivers/crypto/caam/hal/common/hal_jr.c b/core/drivers/crypto/caam/hal/common/hal_jr.c index 1d344b48bf0d80034bd93471368744e16c01fd01..3fab56535f0d9927e6e4fda4a4601e859d8e789b 100644 --- a/core/drivers/crypto/caam/hal/common/hal_jr.c +++ b/core/drivers/crypto/caam/hal/common/hal_jr.c @@ -50,7 +50,7 @@ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr) } while ((reg_val == JRINTR_HALT_ONGOING) && --timeout); if (!timeout || reg_val != JRINTR_HALT_DONE) { - EMSG("Failed to flush job ring\n"); + EMSG("Failed to flush job ring"); return CAAM_FAILURE; } @@ -63,7 +63,7 @@ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr) } while ((reg_val & JRX_JRCR_RESET) && --timeout); if (!timeout) { - EMSG("Failed to reset job ring\n"); + EMSG("Failed to reset job ring"); return CAAM_FAILURE; } diff --git a/core/drivers/crypto/caam/hal/common/hal_rng.c b/core/drivers/crypto/caam/hal/common/hal_rng.c index c98ee4d7769c8b358371b2dfa7891f66d8723b10..5f8f0afc2910bc8e51f136c68169e1d1b60c8a0d 100644 --- a/core/drivers/crypto/caam/hal/common/hal_rng.c +++ b/core/drivers/crypto/caam/hal/common/hal_rng.c @@ -62,6 +62,16 @@ bool caam_hal_rng_key_loaded(vaddr_t baseaddr) return io_caam_read32(baseaddr + RNG_STA) & RNG_STA_SKVN; } +bool caam_hal_rng_pr_enabled(vaddr_t baseaddr) +{ + uint32_t bitmask = RNG_STA_PR0; + + if (caam_hal_rng_get_nb_sh(baseaddr) > 1) + bitmask |= RNG_STA_PR1; + + return (io_caam_read32(baseaddr + RNG_STA) & bitmask) == bitmask; +} + enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay) { uint32_t val = 0; diff --git a/core/drivers/crypto/caam/hal/common/registers/rng_regs.h b/core/drivers/crypto/caam/hal/common/registers/rng_regs.h index f96aceee16303fdf34ae3d6ec95895825d05b8ed..260fef5f5db0e3c704a9ef8a9bff604575b5383b 100644 --- a/core/drivers/crypto/caam/hal/common/registers/rng_regs.h +++ b/core/drivers/crypto/caam/hal/common/registers/rng_regs.h @@ -115,5 +115,7 @@ #define RNG_STA_SKVN BIT32(30) #define RNG_STA_IF1 BIT32(1) #define RNG_STA_IF0 BIT32(0) +#define RNG_STA_PR0 BIT32(4) +#define RNG_STA_PR1 BIT32(5) #endif /* __RNG_REGS_H__ */ diff --git a/core/drivers/crypto/caam/include/caam_desc_defines.h b/core/drivers/crypto/caam/include/caam_desc_defines.h index c6f8f1d603c797e95a4cc94d25bfdd8a0390ff82..f9b6349fdfcd2c26004cc96c47737b729749fbc2 100644 --- a/core/drivers/crypto/caam/include/caam_desc_defines.h +++ b/core/drivers/crypto/caam/include/caam_desc_defines.h @@ -329,6 +329,7 @@ * ECC Protocol Information */ #define PROT_PK_MSG(type) SHIFT_U32(PROT_PK_MSG_##type, 10) +#define PROT_PK_MSG_MES_REP 0 #define PROT_PK_MSG_HASHED 2 #define PROT_PK_TYPE(type) SHIFT_U32(PROT_PK_##type, 1) #define PROT_PK_DL 0 diff --git a/core/drivers/crypto/caam/include/caam_desc_helper.h b/core/drivers/crypto/caam/include/caam_desc_helper.h index bf0de2c90943274eef2a90c41099477380eb7205..ca71cdcf3ddcd8d53a81a4f231210a5ee8b2b7b0 100644 --- a/core/drivers/crypto/caam/include/caam_desc_helper.h +++ b/core/drivers/crypto/caam/include/caam_desc_helper.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * Copyright 2018-2021 NXP + * Copyright 2018-2021, 2024 NXP * * Brief CAAM Descriptor interface. */ @@ -494,18 +494,18 @@ static inline void dump_desc(uint32_t *desc) (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type)) /* - * DSA/ECDSA signature of message hashed + * DSA/ECDSA signature of message of msg_type */ -#define DSA_SIGN(type) \ - (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | PROT_PK_MSG(HASHED) | \ - PROT_PK_TYPE(type)) +#define DSA_SIGN(type, msg_type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | \ + PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type)) /* - * DSA/ECDSA signature verify message hashed + * DSA/ECDSA signature verify message of msg_type */ -#define DSA_VERIFY(type) \ - (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \ - PROT_PK_MSG(HASHED) | PROT_PK_TYPE(type)) +#define DSA_VERIFY(type, msg_type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \ + PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type)) /* * DH/ECC Shared Secret diff --git a/core/drivers/crypto/caam/include/caam_hal_rng.h b/core/drivers/crypto/caam/include/caam_hal_rng.h index 9b87215a828e084775d99c1aaa00cb041f812e52..ef5e19aeb72ddb657fed02d823e43cf426ef5ce9 100644 --- a/core/drivers/crypto/caam/include/caam_hal_rng.h +++ b/core/drivers/crypto/caam/include/caam_hal_rng.h @@ -39,6 +39,13 @@ uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr); */ bool caam_hal_rng_key_loaded(vaddr_t baseaddr); +/* + * Returns true if the RNG was initialized for prediction resistance + * + * @baseaddr RNG Base Address + */ +bool caam_hal_rng_pr_enabled(vaddr_t baseaddr); + /* * Configures the RNG entropy delay * diff --git a/core/drivers/crypto/caam/include/caam_sm.h b/core/drivers/crypto/caam/include/caam_sm.h index 20acc487b5aeb74dc30fa7a3ec0ceb3293fb5e02..5dee43300856df9d85bd82b0b9968afef572e5b5 100644 --- a/core/drivers/crypto/caam/include/caam_sm.h +++ b/core/drivers/crypto/caam/include/caam_sm.h @@ -61,7 +61,8 @@ caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc, * * @sm_page_descriptor Secure Memory page */ -TEE_Result caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor); +enum caam_status +caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor); #else static inline enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg __unused) diff --git a/core/drivers/crypto/hisilicon/hisi_qm.c b/core/drivers/crypto/hisilicon/hisi_qm.c new file mode 100644 index 0000000000000000000000000000000000000000..daf7901a857fd67433258ca14c9c5f42d99eecda --- /dev/null +++ b/core/drivers/crypto/hisilicon/hisi_qm.c @@ -0,0 +1,884 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 HiSilicon Limited. + * Kunpeng hardware accelerator queue management module. + */ +#include "hisi_qm.h" + +#define QM_FVT_CFG_RDY_BIT 0x1 +/* Doorbell */ +#define QM_DOORBELL_SQ_CQ_BASE 0x1000 +#define QM_DB_CMD_SHIFT 12 +#define QM_DB_RAND_DATA_SHIFT 16 +#define QM_DB_INDEX_SHIFT 32 +#define QM_DB_PRIORITY_SHIFT 48 +#define QM_DB_RAND_DATA 0x5a +#define QM_DOORBELL_CMD_SQ 0 +#define QM_DOORBELL_CMD_CQ 1 +/* Mailbox */ +#define QM_MAILBOX_BASE 0x300 +#define QM_MAILBOX_DATA_ADDR_L 0x304 +#define QM_MAILBOX_DATA_ADDR_H 0x308 +#define QM_MB_BUSY_SHIFT 13 +#define QM_MB_BUSY_BIT BIT32(QM_MB_BUSY_SHIFT) +#define QM_MB_OP_SHIFT 14 +#define QM_MB_OP_WR 0 +#define QM_MB_OP_RD 1 +#define QM_MB_STATUS_MASK GENMASK_32(12, 9) +#define QM_MB_WAIT_READY_CNT 10 +#define QM_MB_WAIT_MAX_CNT 21000 +#define QM_MB_WAIT_PERIOD 200 +/* XQC_VFT */ +#define QM_VFT_CFG_OP_ENABLE 0x100054 +#define QM_VFT_CFG_OP_WR 0x100058 +#define QM_VFT_CFG_TYPE 0x10005c +#define QM_VFT_CFG_ADDRESS 0x100060 +#define QM_VFT_CFG_DATA_L 0x100064 +#define QM_VFT_CFG_DATA_H 0x100068 +#define QM_VFT_CFG_RDY 0x10006c +#define QM_SQC_VFT 0 +#define QM_CQC_VFT 1 +#define QM_SQC_VFT_START_SQN_SHIFT 28 +#define QM_SQC_VFT_VALID BIT64(44) +#define QM_SQC_VFT_SQ_NUM_SHIFT 45 +#define QM_CQC_VFT_VALID BIT(28) +#define QM_VFT_WRITE 0 +#define QM_VFT_READ 1 +#define QM_SQC_VFT_BASE_MASK 0x3ff +#define QM_SQC_VFT_NUM_MASK 0x3ff +/* QM INIT */ +#define QM_MEM_START_INIT 0x100040 +#define QM_MEM_INIT_DONE 0x100044 +#define QM_VF_AEQ_INT_MASK 0x4 +#define QM_VF_AEQ_INT_MASK_EN 0x1 +#define QM_VF_EQ_INT_MASK 0xc +#define QM_VF_EQ_INT_MASK_EN 0x1 +#define QM_ARUSER_M_CFG_1 0x100088 +#define QM_ARUSER_M_CFG_ENABLE 0x100090 +#define QM_AWUSER_M_CFG_1 0x100098 +#define QM_AWUSER_M_CFG_ENABLE 0x1000a0 +#define QM_AXUSER_CFG 0x40001070 +#define AXUSER_M_CFG_ENABLE 0x7ffffc +#define QM_AXI_M_CFG 0x1000ac +#define AXI_M_CFG 0xffff +#define QM_PEH_AXUSER_CFG 0x1000cc +#define PEH_AXUSER_CFG 0x400801 +#define QM_CACHE_CTL 0x100050 +#define QM_CACHE_CFG 0x4893 +#define QM_CACHE_WB_START 0x204 +#define QM_CACHE_WB_DONE 0x208 +/* XQC shift */ +#define QM_SQ_SQE_SIZE_SHIFT 12 +#define QM_SQ_ORDER_SHIFT 4 +#define QM_SQ_TYPE_SHIFT 8 +#define QM_CQE_SIZE 4 +#define QM_CQ_CQE_SIZE_SHIFT 12 +/* CQE */ +#define QM_CQE_PHASE(cqe) (((cqe)->w7) & QM_FVT_CFG_RDY_BIT) + +enum qm_mailbox_common_cmd { + QM_MB_CMD_SQC = 0x0, + QM_MB_CMD_CQC, + QM_MB_CMD_EQC, + QM_MB_CMD_AEQC, + QM_MB_CMD_SQC_BT, + QM_MB_CMD_CQC_BT, + QM_MB_CMD_SQC_VFT, +}; + +enum qm_mailbox_cmd_v3 { + QM_MB_CM_CLOSE_QM = 0x7, + QM_MB_CMD_CLOSE_QP, + QM_MB_CMD_FLUSH_QM, + QM_MB_CMD_FLUSH_QP, + QM_MB_CMD_SRC = 0xc, + QM_MB_CMD_DST, + QM_MB_CMD_STOP_QM, +}; + +struct qm_mailbox { + union { + struct { + uint16_t w0; + uint16_t queue; + uint32_t base_l; + uint32_t base_h; + uint32_t token; + }; + uint64_t x[2]; + }; +}; + +struct qm_dfx_registers { + const char *reg_name; + uint32_t reg_offset; +}; + +static const struct qm_dfx_registers qm_dfx_regs[] = { + { .reg_name = "QM_ECC_1BIT_CNT ", .reg_offset = 0x104000 }, + { .reg_name = "QM_ECC_MBIT_CNT ", .reg_offset = 0x104008 }, + { .reg_name = "QM_DFX_MB_CNT ", .reg_offset = 0x104018 }, + { .reg_name = "QM_DFX_DB_CNT ", .reg_offset = 0x104028 }, + { .reg_name = "QM_DFX_SQE_CNT ", .reg_offset = 0x104038 }, + { .reg_name = "QM_DFX_CQE_CNT ", .reg_offset = 0x104048 }, + { .reg_name = "QM_DFX_SEND_SQE_TO_ACC_CNT", .reg_offset = 0x104050 }, + { .reg_name = "QM_DFX_WB_SQE_FROM_ACC_CNT", .reg_offset = 0x104058 }, + { .reg_name = "QM_DFX_ACC_FINISH_CNT ", .reg_offset = 0x104060 }, + { .reg_name = "QM_DFX_CQE_ERR_CNT ", .reg_offset = 0x1040b4 }, + { } +}; + +void hisi_qm_get_version(struct hisi_qm *qm) +{ + qm->version = io_read32(qm->io_base + HISI_QM_REVISON_ID_BASE) & + HISI_QM_REVISON_ID_MASK; +} + +static void qm_db(struct hisi_qm *qm, uint16_t qn, uint8_t cmd, uint16_t index, + uint8_t priority) +{ + uint64_t doorbell = 0; + + doorbell = qn | SHIFT_U64(cmd, QM_DB_CMD_SHIFT) | + SHIFT_U64(QM_DB_RAND_DATA, QM_DB_RAND_DATA_SHIFT) | + SHIFT_U64(index, QM_DB_INDEX_SHIFT) | + SHIFT_U64(priority, QM_DB_PRIORITY_SHIFT); + + io_write64(qm->io_base + QM_DOORBELL_SQ_CQ_BASE, doorbell); +} + +static void qm_mb_write(struct hisi_qm *qm, struct qm_mailbox *mb) +{ + vaddr_t dst = qm->io_base + QM_MAILBOX_BASE; + + write_64bit_pair(dst, mb->x[1], mb->x[0]); + dsb_osh(); +} + +static void qm_mb_read(struct hisi_qm *qm, struct qm_mailbox *mb) +{ + vaddr_t mb_base = qm->io_base + QM_MAILBOX_BASE; + + read_64bit_pair(mb_base, mb->x + 1, mb->x); + dsb_osh(); +} + +static enum hisi_drv_status qm_wait_mb_ready(struct hisi_qm *qm) +{ + struct qm_mailbox mb = { }; + uint32_t timeout = 0; + + timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_READY_CNT); + while (!timeout_elapsed(timeout)) { + /* 128 bits should be read from hardware at one time*/ + qm_mb_read(qm, &mb); + if (!(mb.w0 & QM_MB_BUSY_BIT)) + return HISI_QM_DRVCRYPT_NO_ERR; + } + + EMSG("QM mailbox is busy to start!"); + + return HISI_QM_DRVCRYPT_EBUSY; +} + +static enum hisi_drv_status qm_wait_mb_finish(struct hisi_qm *qm, + struct qm_mailbox *mb) +{ + uint32_t timeout = 0; + + timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_MAX_CNT); + while (!timeout_elapsed(timeout)) { + qm_mb_read(qm, mb); + if (!(mb->w0 & QM_MB_BUSY_BIT)) { + if (mb->w0 & QM_MB_STATUS_MASK) { + EMSG("QM mailbox operation failed!"); + return HISI_QM_DRVCRYPT_EIO; + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + } + } + + return HISI_QM_DRVCRYPT_ETMOUT; +} + +static void qm_mb_init(struct qm_mailbox *mb, uint8_t cmd, uint64_t base, + uint16_t qnum, uint8_t op) +{ + mb->w0 = cmd | SHIFT_U32(op, QM_MB_OP_SHIFT) | QM_MB_BUSY_BIT; + mb->queue = qnum; + reg_pair_from_64(base, &mb->base_h, &mb->base_l); + mb->token = 0; +} + +static enum hisi_drv_status qm_mb_nolock(struct hisi_qm *qm, + struct qm_mailbox *mb) +{ + if (qm_wait_mb_ready(qm)) + return HISI_QM_DRVCRYPT_EBUSY; + + qm_mb_write(qm, mb); + + return qm_wait_mb_finish(qm, mb); +} + +static enum hisi_drv_status hisi_qm_mb_write(struct hisi_qm *qm, uint8_t cmd, + uintptr_t dma_addr, uint16_t qnum) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct qm_mailbox mb = { }; + + qm_mb_init(&mb, cmd, dma_addr, qnum, QM_MB_OP_WR); + mutex_lock(&qm->mailbox_lock); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +static enum hisi_drv_status hisi_qm_mb_read(struct hisi_qm *qm, uint64_t *base, + uint8_t cmd, uint16_t qnum) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct qm_mailbox mb = { }; + + qm_mb_init(&mb, cmd, 0, qnum, QM_MB_OP_RD); + mutex_lock(&qm->mailbox_lock); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + if (ret) + return ret; + + reg_pair_from_64(*base, &mb.base_h, &mb.base_l); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cfg_vft_data(struct hisi_qm *qm, uint8_t vft_type, + uint32_t base, uint32_t number) +{ + uint32_t data_h = 0; + uint32_t data_l = 0; + uint64_t data = 0; + + switch (vft_type) { + case QM_SQC_VFT: + data = SHIFT_U64(base, QM_SQC_VFT_START_SQN_SHIFT) | + QM_SQC_VFT_VALID | + SHIFT_U64((number - 1), QM_SQC_VFT_SQ_NUM_SHIFT); + break; + case QM_CQC_VFT: + data = QM_CQC_VFT_VALID; + break; + default: + panic("Invalid vft type"); + } + + reg_pair_from_64(data, &data_h, &data_l); + io_write32(qm->io_base + QM_VFT_CFG_DATA_L, data_l); + io_write32(qm->io_base + QM_VFT_CFG_DATA_H, data_h); +} + +static enum hisi_drv_status qm_set_vft_common(struct hisi_qm *qm, + uint8_t vft_type, + uint32_t function, + uint32_t base, + uint32_t num) +{ + uint32_t val = 0; + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) { + EMSG("QM VFT is not ready"); + return HISI_QM_DRVCRYPT_EBUSY; + } + + io_write32(qm->io_base + QM_VFT_CFG_OP_WR, QM_VFT_WRITE); + io_write32(qm->io_base + QM_VFT_CFG_TYPE, vft_type); + io_write32(qm->io_base + QM_VFT_CFG_ADDRESS, function); + qm_cfg_vft_data(qm, vft_type, base, num); + io_write32(qm->io_base + QM_VFT_CFG_RDY, 0x0); + io_write32(qm->io_base + QM_VFT_CFG_OP_ENABLE, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) { + EMSG("QM VFT is not ready"); + return HISI_QM_DRVCRYPT_EBUSY; + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm, + uint32_t function, + uint32_t base, uint32_t num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + int i = 0; + + if (!num) { + EMSG("Invalid sq num"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) { + ret = qm_set_vft_common(qm, i, function, base, num); + if (ret) { + EMSG("QM set type %d fail", i); + return ret; + } + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_get_vft(struct hisi_qm *qm, uint32_t *base, + uint32_t *num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint64_t sqc_vft = 0; + + ret = hisi_qm_mb_read(qm, &sqc_vft, QM_MB_CMD_SQC_VFT, 0); + if (ret) + return ret; + + *base = (sqc_vft >> QM_SQC_VFT_START_SQN_SHIFT) & QM_SQC_VFT_BASE_MASK; + *num = ((sqc_vft >> QM_SQC_VFT_SQ_NUM_SHIFT) & QM_SQC_VFT_NUM_MASK) + 1; + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qp_free(struct hisi_qm *qm, uint32_t id) +{ + struct hisi_qp *qp = &qm->qp_array[id]; + + free(qp->sqe); + free(qp->cqe); +} + +static enum hisi_drv_status qp_alloc(struct hisi_qm *qm, uint32_t id) +{ + size_t sq_size = qm->sqe_size * HISI_QM_Q_DEPTH; + size_t cq_size = sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH; + struct hisi_qp *qp = &qm->qp_array[id]; + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + qp->sqe = memalign(HISI_QM_ALIGN128, sq_size); + if (!qp->sqe) { + EMSG("Fail to malloc sq[%"PRIu32"]", id); + return HISI_QM_DRVCRYPT_ENOMEM; + } + qp->sqe_dma = virt_to_phys(qp->sqe); + qp->cqe = memalign(HISI_QM_ALIGN32, cq_size); + if (!qp->cqe) { + EMSG("Fail to malloc cq[%"PRIu32"]", id); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_sqe; + } + qp->cqe_dma = virt_to_phys(qp->cqe); + + qp->qp_id = id; + qp->qm = qm; + return HISI_QM_DRVCRYPT_NO_ERR; + +free_sqe: + free(qp->sqe); + return ret; +} + +static void hisi_qm_free_xqc(struct qm_xqc *xqc) +{ + free(xqc->cqc); + free(xqc->sqc); +} + +static void qm_free(struct hisi_qm *qm) +{ + unsigned int i = 0; + + for (i = 0; i < qm->qp_num; i++) + qp_free(qm, i); + + free(qm->qp_array); + hisi_qm_free_xqc(&qm->xqc); + hisi_qm_free_xqc(&qm->cfg_xqc); +} + +static enum hisi_drv_status hisi_qm_alloc_xqc(struct qm_xqc *xqc, + uint32_t qp_num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + size_t sqc_size = 0; + size_t cqc_size = 0; + + sqc_size = sizeof(struct qm_sqc) * qp_num; + cqc_size = sizeof(struct qm_cqc) * qp_num; + + xqc->sqc = memalign(HISI_QM_ALIGN32, sqc_size); + if (!xqc->sqc) { + EMSG("Fail to malloc sqc"); + return HISI_QM_DRVCRYPT_ENOMEM; + } + memset(xqc->sqc, 0, sqc_size); + xqc->sqc_dma = virt_to_phys(xqc->sqc); + + xqc->cqc = memalign(HISI_QM_ALIGN32, cqc_size); + if (!xqc->cqc) { + EMSG("Fail to malloc cqc"); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_sqc; + } + memset(xqc->cqc, 0, cqc_size); + xqc->cqc_dma = virt_to_phys(xqc->cqc); + + return HISI_QM_DRVCRYPT_NO_ERR; + + free(xqc->cqc); +free_sqc: + free(xqc->sqc); + return ret; +} + +static enum hisi_drv_status qm_alloc(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + int32_t j; + uint32_t i; + + ret = hisi_qm_alloc_xqc(&qm->xqc, qm->qp_num); + if (ret) + return ret; + + ret = hisi_qm_alloc_xqc(&qm->cfg_xqc, 1); + if (ret) + goto free_xqc; + + qm->qp_array = calloc(qm->qp_num, sizeof(struct hisi_qp)); + if (!qm->qp_array) { + EMSG("Fail to malloc qp_array"); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_cfg_xqc; + } + + for (i = 0; i < qm->qp_num; i++) { + ret = qp_alloc(qm, i); + if (ret) + goto free_qp_mem; + } + + return HISI_QM_DRVCRYPT_NO_ERR; + +free_qp_mem: + for (j = (int)i - 1; j >= 0; j--) + qp_free(qm, j); + free(qm->qp_array); +free_cfg_xqc: + hisi_qm_free_xqc(&qm->cfg_xqc); +free_xqc: + hisi_qm_free_xqc(&qm->xqc); + return ret; +} + +enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->fun_type == HISI_QM_HW_VF) { + ret = qm_get_vft(qm, &qm->qp_base, &qm->qp_num); + if (ret) { + EMSG("Fail to get function vft config"); + return ret; + } + } + + if (!qm->qp_num || !qm->sqe_size) { + EMSG("Invalid QM parameters"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + ret = qm_alloc(qm); + if (ret) + return ret; + + qm->qp_in_used = 0; + qm->qp_idx = 0; + mutex_init(&qm->qp_lock); + mutex_init(&qm->mailbox_lock); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cache_writeback(struct hisi_qm *qm) +{ + uint32_t val = 0; + + io_write32(qm->io_base + QM_CACHE_WB_START, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_CACHE_WB_DONE, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) + panic("QM writeback sqc cache fail"); +} + +void hisi_qm_uninit(struct hisi_qm *qm) +{ + qm_cache_writeback(qm); + qm_free(qm); + mutex_destroy(&qm->qp_lock); + mutex_destroy(&qm->mailbox_lock); +} + +static enum hisi_drv_status qm_hw_mem_reset(struct hisi_qm *qm) +{ + uint32_t val = 0; + + io_write32(qm->io_base + QM_MEM_START_INIT, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_MEM_INIT_DONE, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) + return HISI_QM_DRVCRYPT_EBUSY; + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_func_vft_cfg(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint32_t q_base = qm->qp_num; + uint32_t act_q_num = 0; + unsigned int i = 0; + unsigned int j = 0; + + if (!qm->vfs_num) + return HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->vfs_num > HISI_QM_MAX_VFS_NUM) { + EMSG("Invalid QM vfs_num"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + for (i = 1; i <= qm->vfs_num; i++) { + act_q_num = HISI_QM_VF_Q_NUM; + ret = qm_set_xqc_vft(qm, i, q_base, act_q_num); + if (ret) { + for (j = 1; j < i; j++) + (void)qm_set_xqc_vft(qm, j, 0, 0); + return ret; + } + q_base += act_q_num; + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->fun_type == HISI_QM_HW_PF) { + ret = qm_hw_mem_reset(qm); + if (ret) { + EMSG("Fail to reset QM hardware mem"); + return ret; + } + + ret = qm_set_xqc_vft(qm, 0, qm->qp_base, qm->qp_num); + if (ret) { + EMSG("Fail to set PF xqc_vft"); + return ret; + } + + ret = qm_func_vft_cfg(qm); + if (ret) { + EMSG("Fail to set VF xqc_vft"); + return ret; + } + } + + ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->xqc.sqc_dma, 0); + if (ret) { + EMSG("Fail to set sqc_bt"); + return ret; + } + + ret = hisi_qm_mb_write(qm, QM_MB_CMD_CQC_BT, qm->xqc.cqc_dma, 0); + if (ret) { + EMSG("Fail to set cqc_bt"); + return ret; + } + + /* Security mode does not support msi */ + io_write32(qm->io_base + QM_VF_AEQ_INT_MASK, QM_VF_AEQ_INT_MASK_EN); + io_write32(qm->io_base + QM_VF_EQ_INT_MASK, QM_VF_EQ_INT_MASK_EN); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +void hisi_qm_dev_init(struct hisi_qm *qm) +{ + if (qm->fun_type == HISI_QM_HW_VF) + return; + + /* QM user domain */ + io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG); + io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); + io_write32(qm->io_base + QM_AWUSER_M_CFG_1, QM_AXUSER_CFG); + io_write32(qm->io_base + QM_AWUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); + /* QM cache */ + io_write32(qm->io_base + QM_AXI_M_CFG, AXI_M_CFG); + + if (qm->version == HISI_QM_HW_V2) { + /* Disable FLR triggered by BME(bus master enable) */ + io_write32(qm->io_base + QM_PEH_AXUSER_CFG, PEH_AXUSER_CFG); + /* Set sec sqc and cqc cache wb threshold 4 */ + io_write32(qm->io_base + QM_CACHE_CTL, QM_CACHE_CFG); + } + /* Disable QM ras */ + io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK, + HISI_QM_ABNML_INT_MASK_CFG); +} + +static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_sqc *sqc = qm->cfg_xqc.sqc; + struct qm_mailbox mb = { }; + + mutex_lock(&qm->mailbox_lock); + memset(sqc, 0, sizeof(struct qm_sqc)); + reg_pair_from_64(qp->sqe_dma, &sqc->base_h, &sqc->base_l); + sqc->dw3 = (HISI_QM_Q_DEPTH - 1) | + SHIFT_U32(qm->sqe_log2_size, QM_SQ_SQE_SIZE_SHIFT); + sqc->rand_data = QM_DB_RAND_DATA; + sqc->cq_num = qp->qp_id; + sqc->w13 = BIT32(QM_SQ_ORDER_SHIFT) | + SHIFT_U32(qp->sq_type, QM_SQ_TYPE_SHIFT); + + qm_mb_init(&mb, QM_MB_CMD_SQC, qm->cfg_xqc.sqc_dma, qp->qp_id, + QM_MB_OP_WR); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +static enum hisi_drv_status qm_cqc_cfg(struct hisi_qp *qp) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_cqc *cqc = qm->cfg_xqc.cqc; + struct qm_mailbox mb = { }; + + mutex_lock(&qm->mailbox_lock); + memset(cqc, 0, sizeof(struct qm_cqc)); + reg_pair_from_64(qp->cqe_dma, &cqc->base_h, &cqc->base_l); + cqc->dw3 = (HISI_QM_Q_DEPTH - 1) | + SHIFT_U32(QM_CQE_SIZE, QM_CQ_CQE_SIZE_SHIFT); + cqc->rand_data = QM_DB_RAND_DATA; + cqc->dw6 = PHASE_DEFAULT_VAL; + + qm_mb_init(&mb, QM_MB_CMD_CQC, qm->cfg_xqc.cqc_dma, qp->qp_id, + QM_MB_OP_WR); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type) +{ + struct hisi_qp *qp = NULL; + int cur_idx = 0; + uint32_t i = 0; + + mutex_lock(&qm->qp_lock); + if (qm->qp_in_used == qm->qp_num) { + EMSG("All %"PRIu32" queues of QM are busy", qm->qp_num); + goto err_proc; + } + + for (i = 0; i < qm->qp_num; i++) { + cur_idx = (qm->qp_idx + i) % qm->qp_num; + if (!qm->qp_array[cur_idx].used) { + qm->qp_array[cur_idx].used = true; + qm->qp_idx = cur_idx + 1; + break; + } + } + + qp = qm->qp_array + cur_idx; + memset(qp->cqe, 0, sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH); + qp->sq_type = sq_type; + qp->sq_tail = 0; + qp->cq_head = 0; + qp->cqc_phase = true; + + if (qm_sqc_cfg(qp)) { + EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id); + goto err_proc; + } + + if (qm_cqc_cfg(qp)) { + EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id); + goto err_proc; + } + + qm->qp_in_used++; + mutex_unlock(&qm->qp_lock); + return qp; + +err_proc: + qp->sq_type = 0; + qp->cqc_phase = false; + mutex_unlock(&qm->qp_lock); + return NULL; +} + +void hisi_qm_release_qp(struct hisi_qp *qp) +{ + struct hisi_qm *qm = NULL; + + if (!qp) { + EMSG("QP is NULL"); + return; + } + + qm = qp->qm; + mutex_lock(&qm->qp_lock); + qm->qp_in_used--; + qp->used = false; + mutex_unlock(&qm->qp_lock); +} + +static void qm_sq_tail_update(struct hisi_qp *qp) +{ + if (qp->sq_tail == HISI_QM_Q_DEPTH - 1) + qp->sq_tail = 0; + else + qp->sq_tail++; +} + +/* + * One task thread will just bind to one hardware queue, and + * hardware does not support msi. So we have no lock here. + */ +enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = NULL; + void *sqe = NULL; + + if (!qp) { + EMSG("QP is NULL"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + qm = qp->qm; + ret = qm->dev_status_check(qm); + if (ret) + return ret; + + sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * qp->sq_tail); + memset(sqe, 0, qm->sqe_size); + + ret = qp->fill_sqe(sqe, msg); + if (ret) { + EMSG("Fail to fill sqe"); + return ret; + } + + qm_sq_tail_update(qp); + + dsb(); + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp->sq_tail, 0); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cq_head_update(struct hisi_qp *qp) +{ + if (qp->cq_head == HISI_QM_Q_DEPTH - 1) { + qp->cqc_phase = !qp->cqc_phase; + qp->cq_head = 0; + } else { + qp->cq_head++; + } +} + +static enum hisi_drv_status hisi_qp_recv(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_cqe *cqe = NULL; + void *sqe = NULL; + + ret = qm->dev_status_check(qm); + if (ret) + return ret; + + cqe = qp->cqe + qp->cq_head; + if (QM_CQE_PHASE(cqe) == qp->cqc_phase) { + dsb_osh(); + sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * cqe->sq_head); + ret = qp->parse_sqe(sqe, msg); + qm_cq_head_update(qp); + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->cq_head, 0); + if (ret) { + EMSG("Fail to parse sqe"); + return ret; + } + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + + return HISI_QM_DRVCRYPT_RECV_DONE; +} + +static void qm_dfx_dump(struct hisi_qm *qm) +{ + const struct qm_dfx_registers *regs = qm_dfx_regs; + __maybe_unused uint32_t val = 0; + + if (qm->fun_type == HISI_QM_HW_VF) + return; + + while (regs->reg_name) { + val = io_read32(qm->io_base + regs->reg_offset); + EMSG("%s= 0x%" PRIx32, regs->reg_name, val); + regs++; + } +} + +enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint32_t timeout = 0; + + if (!qp) { + EMSG("QP is NULL"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + timeout = timeout_init_us(QM_SINGLE_WAIT_TIME * + HISI_QM_RECV_SYNC_TIMEOUT); + while (!timeout_elapsed(timeout)) { + ret = hisi_qp_recv(qp, msg); + if (ret) { + if (ret != HISI_QM_DRVCRYPT_RECV_DONE) { + EMSG("QM recv task error"); + qm_dfx_dump(qp->qm); + return ret; + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + } + } + + EMSG("QM recv task timeout"); + qm_dfx_dump(qp->qm); + return HISI_QM_DRVCRYPT_ETMOUT; +} diff --git a/core/drivers/crypto/hisilicon/include/hisi_qm.h b/core/drivers/crypto/hisilicon/include/hisi_qm.h new file mode 100644 index 0000000000000000000000000000000000000000..8ea1f6fc1d0146d9ccbabeb46800a5d56f4c47d8 --- /dev/null +++ b/core/drivers/crypto/hisilicon/include/hisi_qm.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2023, Huawei Technologies Co., Ltd + */ +#ifndef __HISI_QM_H__ +#define __HISI_QM_H__ + +#include <io.h> +#include <kernel/delay.h> +#include <kernel/mutex.h> +#include <kernel/panic.h> +#include <mm/core_memprot.h> +#include <stdlib.h> +#include <string.h> +#include <string_ext.h> +#include <sys/queue.h> + +#define HISI_QM_HW_V2 0x21 +#define HISI_QM_HW_V3 0x30 +#define HISI_QM_MAX_VFS_NUM 63 +#define HISI_QM_PF_Q_BASE 0 +#define HISI_QM_PF_Q_NUM 64 +#define HISI_QM_VF_Q_NUM 15 +#define HISI_QM_Q_DEPTH 8 +#define PHASE_DEFAULT_VAL 0x1 + +#define HISI_QM_ABNML_INT_MASK 0x100004 +#define HISI_QM_ABNML_INT_MASK_CFG 0x7fff +#define HISI_QM_ABNML_INT_SRC 0x100000 +#define HISI_QM_HPRE_NFE_INT_MASK 0x6fb7 +#define HISI_QM_SEC_NFE_INT_MASK 0x6ff7 +#define HISI_QM_INVALID_DB BIT(12) +#define HISI_QM_REVISON_ID_BASE 0x1000dc +#define HISI_QM_REVISON_ID_MASK GENMASK_32(7, 0) +#define POLL_PERIOD 10 +#define POLL_TIMEOUT 1000 +#define HISI_QM_RECV_SYNC_TIMEOUT 0xfffff +#define HISI_QM_ALIGN128 128 +#define HISI_QM_ALIGN32 32 +#define QM_SINGLE_WAIT_TIME 5 +#define ADDR_U64(upper, lower) ((uint64_t)(upper) << 32 | (lower)) + +enum qm_fun_type { + HISI_QM_HW_PF, + HISI_QM_HW_VF, +}; + +enum qm_sq_type { + HISI_QM_CHANNEL_TYPE0 = 0, + HISI_QM_CHANNEL_TYPE1, + HISI_QM_CHANNEL_TYPE2, +}; + +struct qm_sqc { + uint16_t head; + uint16_t tail; + uint32_t base_l; + uint32_t base_h; + /* + * qes : 12 + * sqe : 4 + * rsv(stash_nid/stash_en) : 16 + */ + uint32_t dw3; + uint16_t rand_data; + uint16_t rsv0; + uint16_t pasid; + /* + * rsv : 5 + * head_sig : 1 + * tail_sig : 1 + * pasid_en : 1 + * rsv : 8 + */ + uint16_t w11; + uint16_t cq_num; + /* + * priority(Credit): 4 + * order(order/fc/close/rsv) : 4 + * type : 4 + * rsv : 4 + */ + uint16_t w13; + uint32_t rsv1; +}; + +struct qm_cqc { + uint16_t head; + uint16_t tail; + uint32_t base_l; + uint32_t base_h; + /* + * qes : 12 + * cqe_size : 4 + * rsv(stash_nid/stash_en) : 16 + */ + uint32_t dw3; + uint16_t rand_data; + uint16_t rsv0; + uint16_t pasid; + /* + * pasid_en : 1 + * rsv : 4 + * head_sig : 1 + * tail_sig : 1 + * rsv : 9 + */ + uint16_t w11; + /* + * phase : 1 + * c_flag : 1 + * stash_vld : 1 + */ + uint32_t dw6; + uint32_t rsv1; +}; + +struct qm_cqe { + uint32_t rsv0; + uint16_t cmd_id; + uint16_t rsv1; + uint16_t sq_head; + uint16_t sq_id; + uint16_t rsv2; + /* + * p : 1 + * status : 15 + */ + uint16_t w7; +}; + +struct hisi_qp { + struct hisi_qm *qm; + uint32_t qp_id; + uint8_t sq_type; + uint16_t sq_tail; + uint16_t cq_head; + bool cqc_phase; + bool used; + + void *sqe; + struct qm_cqe *cqe; + paddr_t sqe_dma; + paddr_t cqe_dma; + + enum hisi_drv_status (*fill_sqe)(void *sqe, void *msg); + enum hisi_drv_status (*parse_sqe)(void *sqe, void *msg); +}; + +struct qm_xqc { + struct qm_sqc *sqc; + struct qm_cqc *cqc; + paddr_t sqc_dma; + paddr_t cqc_dma; +}; + +struct hisi_qm { + enum qm_fun_type fun_type; + vaddr_t io_base; + uint32_t io_size; + uint32_t vfs_num; + uint32_t version; + + struct qm_xqc xqc; + struct qm_xqc cfg_xqc; + uint32_t sqe_size; + uint32_t sqe_log2_size; + uint32_t qp_base; + uint32_t qp_num; + uint32_t qp_in_used; + uint32_t qp_idx; + struct hisi_qp *qp_array; + struct mutex qp_lock; /* protect the qp instance */ + struct mutex mailbox_lock; + + enum hisi_drv_status (*dev_status_check)(struct hisi_qm *qm); +}; + +enum hisi_drv_status { + HISI_QM_DRVCRYPT_NO_ERR = 0, + HISI_QM_DRVCRYPT_FAIL = 1, + HISI_QM_DRVCRYPT_EIO = 5, + HISI_QM_DRVCRYPT_EAGAIN = 11, + HISI_QM_DRVCRYPT_ENOMEM = 12, + HISI_QM_DRVCRYPT_EFAULT = 14, + HISI_QM_DRVCRYPT_EBUSY = 16, + HISI_QM_DRVCRYPT_ENODEV = 19, + HISI_QM_DRVCRYPT_EINVAL = 22, + HISI_QM_DRVCRYPT_ETMOUT = 110, + HISI_QM_DRVCRYPT_RECV_DONE = 175, + HISI_QM_DRVCRYPT_ENOPROC, + HISI_QM_DRVCRYPT_IN_EPARA, + HISI_QM_DRVCRYPT_VERIFY_ERR, + HISI_QM_DRVCRYPT_HW_EACCESS, +}; + +struct acc_device { + struct hisi_qm qm; + vaddr_t io_base; + uint32_t io_size; + uint32_t vfs_num; + uint32_t endian; + enum qm_fun_type fun_type; + SLIST_ENTRY(acc_device) link; +}; + +/** + * @Description: Get the version information of QM hardware + * @param qm: Handle of Queue Management module + */ +void hisi_qm_get_version(struct hisi_qm *qm); + +/** + * @Description: Init QM for Kunpeng drv + * @param qm: Handle of Queue Management module + * @return success: HISI_QM_DRVCRYPT_NO_ERR, + * fail: HISI_QM_DRVCRYPT_EBUSY/HISI_QM_DRVCRYPT_EINVAL + */ +enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm); + +/** + * @Description:deinit QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +void hisi_qm_uninit(struct hisi_qm *qm); + +/** + * @Description: Start QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm); + +/** + * @Description: Config QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +void hisi_qm_dev_init(struct hisi_qm *qm); + +/** + * @Description: Create Queue Pair, allocated to PF/VF for configure + * and service use. Each QP includes one SQ and one CQ + * @param qm: Handle of Queue Management module + * @param sq_type: Accelerator specific algorithm type in sqc + * @return success: Handle of QP,fail: NULL + */ +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type); + +/** + * @Description:Release Queue Pair + * @param qp: Handle of Queue Pair + */ +void hisi_qm_release_qp(struct hisi_qp *qp); + +/** + * @Description: Send SQE(Submmision Queue Element) to Kunpeng dev + * @param qp: Handle of Queue Pair + * @param msg: The message + * @return success: HISI_QM_DRVCRYPT_NO_ERR,fail: HISI_QM_DRVCRYPT_EINVAL + */ +enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg); + +/** + * @Description: Recevice result from Kunpeng dev + * @param qp: Handle of Queue Pair + * @param msg: The message + * @return success: HISI_QM_DRVCRYPT_NO_ERR + * fail: HISI_QM_DRVCRYPT_EINVAL/ETMOUT + */ +enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg); + +#endif diff --git a/core/drivers/crypto/hisilicon/sub.mk b/core/drivers/crypto/hisilicon/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..9a1747084ffdebe8fa20127a387a4d1824f23bdb --- /dev/null +++ b/core/drivers/crypto/hisilicon/sub.mk @@ -0,0 +1,3 @@ +incdirs-y += include + +srcs-y += hisi_qm.c diff --git a/core/drivers/crypto/sub.mk b/core/drivers/crypto/sub.mk index 3c26eda79a25f0723729beaa6f637d0f04d170c3..71cb6bd6905aa3e0b1233e3314a32c071acf8e78 100644 --- a/core/drivers/crypto/sub.mk +++ b/core/drivers/crypto/sub.mk @@ -11,3 +11,5 @@ subdirs-$(CFG_STM32_CRYPTO_DRIVER) += stm32 subdirs-$(CFG_ASPEED_CRYPTO_DRIVER) += aspeed subdirs-$(CFG_VERSAL_CRYPTO_DRIVER) += versal + +subdirs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisilicon diff --git a/core/drivers/dra7_rng.c b/core/drivers/dra7_rng.c index c3af33594a818553746d89e364d35b9c176a3d86..caea21ea1646ec1e6e15f0a70910aa09f526c6c1 100644 --- a/core/drivers/dra7_rng.c +++ b/core/drivers/dra7_rng.c @@ -92,7 +92,7 @@ static void dra7_rng_read64(uint32_t *low_word, uint32_t *high_word) /* Clear the shutdown overflow event */ io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO); - DMSG("Fixed FRO shutdown\n"); + DMSG("Fixed FRO shutdown"); } } /* Read random value */ diff --git a/core/drivers/gic.c b/core/drivers/gic.c index 6d5b7777c52184b578c35e449178655c2da1b778..e751ae4e5c56c9840297c996cd0f66d963aebcc7 100644 --- a/core/drivers/gic.c +++ b/core/drivers/gic.c @@ -1,24 +1,27 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2016-2017, Linaro Limited + * Copyright (c) 2016-2017, 2023 Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include <arm.h> #include <assert.h> -#include <config.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> #include <compiler.h> +#include <config.h> #include <drivers/gic.h> +#include <io.h> #include <keep.h> #include <kernel/dt.h> +#include <kernel/dt_driver.h> #include <kernel/interrupt.h> +#include <kernel/misc.h> #include <kernel/panic.h> +#include <libfdt.h> #include <mm/core_memprot.h> #include <mm/core_mmu.h> -#include <libfdt.h> -#include <util.h> -#include <io.h> #include <trace.h> +#include <util.h> /* Offsets from gic.gicc_base */ #define GICC_CTLR (0x000) @@ -28,7 +31,6 @@ #define GICC_CTLR_ENABLEGRP0 (1 << 0) #define GICC_CTLR_ENABLEGRP1 (1 << 1) -#define GICD_CTLR_ENABLEGRP1S (1 << 2) #define GICC_CTLR_FIQEN (1 << 3) /* Offsets from gic.gicd_base */ @@ -44,8 +46,39 @@ #define GICD_IGROUPMODR(n) (0xd00 + (n) * 4) #define GICD_SGIR (0xF00) -#define GICD_CTLR_ENABLEGRP0 (1 << 0) -#define GICD_CTLR_ENABLEGRP1 (1 << 1) +#ifdef CFG_ARM_GICV3 +#define GICD_PIDR2 (0xFFE8) +#else +/* Called ICPIDR2 in GICv2 specification */ +#define GICD_PIDR2 (0xFE8) +#endif + +#define GICD_CTLR_ENABLEGRP0 BIT32(0) +#define GICD_CTLR_ENABLEGRP1NS BIT32(1) +#define GICD_CTLR_ENABLEGRP1S BIT32(2) +#define GICD_CTLR_ARE_S BIT32(4) +#define GICD_CTLR_ARE_NS BIT32(5) + +/* Offsets from gic.gicr_base[core_pos] */ +#define GICR_V3_PCPUBASE_SIZE (2 * 64 * 1024) +#define GICR_SGI_BASE_OFFSET (64 * 1024) +#define GICR_CTLR (0x00) +#define GICR_TYPER (0x08) + +#define GICR_IGROUPR0 (GICR_SGI_BASE_OFFSET + 0x080) +#define GICR_IGRPMODR0 (GICR_SGI_BASE_OFFSET + 0xD00) +#define GICR_ICENABLER0 (GICR_SGI_BASE_OFFSET + 0x180) +#define GICR_ICPENDR0 (GICR_SGI_BASE_OFFSET + 0x280) + +#define GICR_TYPER_LAST BIT64(4) +#define GICR_TYPER_AFF3_SHIFT 56 +#define GICR_TYPER_AFF2_SHIFT 48 +#define GICR_TYPER_AFF1_SHIFT 40 +#define GICR_TYPER_AFF0_SHIFT 32 + +/* GICD IDR2 name differs on GICv3 and GICv2 but uses same bit map */ +#define GICD_PIDR2_ARCHREV_SHIFT 4 +#define GICD_PIDR2_ARCHREV_MASK 0xF /* Number of Private Peripheral Interrupt */ #define NUM_PPI 32 @@ -71,10 +104,27 @@ #define GICC_IAR_CPU_ID_MASK 0x7 #define GICC_IAR_CPU_ID_SHIFT 10 +#define GICC_SGI_IRM_BIT 40 +#define GICC_SGI_AFF1_SHIFT 16 +#define GICC_SGI_AFF2_SHIFT 32 +#define GICC_SGI_AFF3_SHIFT 48 + +#define GICD_SGIR_SIGINTID_MASK 0xf +#define GICD_SGIR_TO_OTHER_CPUS 0x1 +#define GICD_SGIR_TO_THIS_CPU 0x2 +#define GICD_SGIR_TARGET_LIST_FILTER_SHIFT 24 +#define GICD_SGIR_NSATT_SHIFT 15 +#define GICD_SGIR_CPU_TARGET_LIST_SHIFT 16 + struct gic_data { vaddr_t gicc_base; vaddr_t gicd_base; +#if defined(CFG_ARM_GICV3) + vaddr_t gicr_base[CFG_TEE_CORE_NB_CORE]; +#endif size_t max_it; + uint32_t per_cpu_group_status; + uint32_t per_cpu_group_modifier; struct itr_chip chip; }; @@ -86,7 +136,7 @@ static void gic_op_enable(struct itr_chip *chip, size_t it); static void gic_op_disable(struct itr_chip *chip, size_t it); static void gic_op_raise_pi(struct itr_chip *chip, size_t it); static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, - uint8_t cpu_mask); + uint32_t cpu_mask); static void gic_op_set_affinity(struct itr_chip *chip, size_t it, uint8_t cpu_mask); @@ -102,6 +152,21 @@ static const struct itr_ops gic_ops = { }; DECLARE_KEEP_PAGER(gic_ops); +static vaddr_t __maybe_unused get_gicr_base(struct gic_data *gd __maybe_unused) +{ +#if defined(CFG_ARM_GICV3) + return gd->gicr_base[get_core_pos()]; +#else + return 0; +#endif +} + +static bool affinity_routing_is_enabled(struct gic_data *gd) +{ + return IS_ENABLED(CFG_ARM_GICV3) && + io_read32(gd->gicd_base + GICD_CTLR) & GICD_CTLR_ARE_S; +} + static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base) { int i; @@ -145,24 +210,95 @@ out: return ret; } -void gic_cpu_init(void) +static void gicv3_sync_sgi_config(struct gic_data *gd) { - struct gic_data *gd = &gic_data; - -#if defined(CFG_ARM_GICV3) - assert(gd->gicd_base); -#else - assert(gd->gicd_base && gd->gicc_base); -#endif + vaddr_t gicr_base = get_gicr_base(gd); + bool need_sync = false; + uint32_t gmod0 = 0; + uint32_t grp0 = 0; + size_t n = 0; - /* per-CPU interrupts config: - * ID0-ID7(SGI) for Non-secure interrupts - * ID8-ID15(SGI) for Secure interrupts. - * All PPI config as Non-secure interrupts. + /* + * If gicr_base isn't available there's no need to synchronize SGI + * configuration since gic_init_donate_sgi_to_ns() would panic. */ - io_write32(gd->gicd_base + GICD_IGROUPR(0), 0xffff00ff); + if (!gicr_base) + return; + + grp0 = io_read32(gicr_base + GICR_IGROUPR0); + gmod0 = io_read32(gicr_base + GICR_IGRPMODR0); + for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) { + /* Ignore matching bits */ + if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) && + !(BIT32(n) & (gmod0 ^ gd->per_cpu_group_modifier))) + continue; + /* + * SGI-n differs from primary CPU configuration, + * let's sync up. + */ + need_sync = true; + + /* Disable interrupt */ + io_write32(gicr_base + GICR_ICENABLER0, BIT32(n)); + + /* Make interrupt non-pending */ + io_write32(gicr_base + GICR_ICPENDR0, BIT32(n)); + + if (BIT32(n) & gd->per_cpu_group_status) + grp0 |= BIT32(n); + else + grp0 &= ~BIT32(n); + if (BIT32(n) & gd->per_cpu_group_modifier) + gmod0 |= BIT32(n); + else + gmod0 &= ~BIT32(n); + } - /* Set the priority mask to permit Non-secure interrupts, and to + if (need_sync) { + io_write32(gicr_base + GICR_IGROUPR0, grp0); + io_write32(gicr_base + GICR_IGRPMODR0, gmod0); + } +} + +static void gic_legacy_sync_sgi_config(struct gic_data *gd) +{ + bool need_sync = false; + uint32_t grp0 = 0; + size_t n = 0; + + grp0 = io_read32(gd->gicd_base + GICD_IGROUPR(0)); + for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) { + /* Ignore matching bits */ + if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status))) + continue; + /* + * SGI-n differs from primary CPU configuration, + * let's sync up. + */ + need_sync = true; + + /* Disable interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(n)); + + /* Make interrupt non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(n)); + + if (BIT32(n) & gd->per_cpu_group_status) + grp0 |= BIT32(n); + else + grp0 &= ~BIT32(n); + } + + if (need_sync) + io_write32(gd->gicd_base + GICD_IGROUPR(0), grp0); +} + +static void init_gic_per_cpu(struct gic_data *gd) +{ + io_write32(gd->gicd_base + GICD_IGROUPR(0), gd->per_cpu_group_status); + + /* + * Set the priority mask to permit Non-secure interrupts, and to * allow the Non-secure world to adjust the priority mask itself */ #if defined(CFG_ARM_GICV3) @@ -178,6 +314,76 @@ void gic_cpu_init(void) #endif } +void gic_init_per_cpu(void) +{ + struct gic_data *gd = &gic_data; + +#if defined(CFG_ARM_GICV3) + assert(gd->gicd_base); +#else + assert(gd->gicd_base && gd->gicc_base); +#endif + + if (IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { + /* + * GIC is already initialized by TF-A, we only need to + * handle eventual SGI configuration changes. + */ + if (affinity_routing_is_enabled(gd)) + gicv3_sync_sgi_config(gd); + else + gic_legacy_sync_sgi_config(gd); + } else { + /* + * Non-TF-A case where all CPU specific configuration + * of GIC must be done here. + */ + init_gic_per_cpu(gd); + } +} + +void gic_init_donate_sgi_to_ns(size_t it) +{ + struct gic_data *gd = &gic_data; + + assert(it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX); + + /* Assert it's secure to start with. */ + assert(!(gd->per_cpu_group_status & BIT32(it)) && + (gd->per_cpu_group_modifier & BIT32(it))); + + gd->per_cpu_group_modifier &= ~BIT32(it); + gd->per_cpu_group_status |= BIT32(it); + + if (affinity_routing_is_enabled(gd)) { + vaddr_t gicr_base = get_gicr_base(gd); + + if (!gicr_base) + panic("GICR_BASE missing"); + + /* Disable interrupt */ + io_write32(gicr_base + GICR_ICENABLER0, BIT32(it)); + + /* Make interrupt non-pending */ + io_write32(gicr_base + GICR_ICPENDR0, BIT32(it)); + + /* Make it to non-secure */ + io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status); + io_write32(gicr_base + GICR_IGRPMODR0, + gd->per_cpu_group_modifier); + } else { + /* Disable interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(it)); + + /* Make interrupt non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(it)); + + /* Make it to non-secure */ + io_write32(gd->gicd_base + GICD_IGROUPR(0), + gd->per_cpu_group_status); + } +} + static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type, uint32_t *prio) { @@ -195,10 +401,10 @@ static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type, it_num = fdt32_to_cpu(properties[1]); switch (fdt32_to_cpu(properties[0])) { - case 1: + case GIC_PPI: it_num += 16; break; - case 0: + case GIC_SPI: it_num += 32; break; default: @@ -208,11 +414,54 @@ static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type, return it_num; } -static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa) +static void __maybe_unused probe_redist_base_addrs(vaddr_t *gicr_base_addrs, + paddr_t gicr_base_pa) +{ + size_t sz = GICR_V3_PCPUBASE_SIZE; + paddr_t pa = gicr_base_pa; + size_t core_pos = 0; + uint64_t mt_bit = 0; + uint64_t mpidr = 0; + uint64_t tv = 0; + vaddr_t va = 0; + +#ifdef ARM64 + mt_bit = read_mpidr_el1() & MPIDR_MT_MASK; +#endif + do { + va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); + if (!va) + panic(); + tv = io_read64(va + GICR_TYPER); + + /* + * Extract an mpidr from the Type register to calculate the + * core position of this redistributer instance. + */ + mpidr = mt_bit; + mpidr |= SHIFT_U64((tv >> GICR_TYPER_AFF3_SHIFT) & + MPIDR_AFFLVL_MASK, MPIDR_AFF3_SHIFT); + mpidr |= (tv >> GICR_TYPER_AFF0_SHIFT) & + (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | MPIDR_AFF2_MASK); + core_pos = get_core_pos_mpidr(mpidr); + if (core_pos < CFG_TEE_CORE_NB_CORE) { + DMSG("GICR_BASE[%zu] at %#"PRIxVA, core_pos, va); + gicr_base_addrs[core_pos] = va; + } else { + EMSG("Skipping too large core_pos %zu from GICR_TYPER", + core_pos); + } + pa += sz; + } while (!(tv & GICR_TYPER_LAST)); +} + +static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa __maybe_unused) { struct gic_data *gd = &gic_data; vaddr_t gicc_base = 0; vaddr_t gicd_base = 0; + uint32_t vers __maybe_unused = 0; assert(cpu_mmu_enabled()); @@ -221,7 +470,14 @@ static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa) if (!gicd_base) panic(); - if (!IS_ENABLED(CFG_ARM_GICV3)) { + vers = io_read32(gicd_base + GICD_PIDR2); + vers >>= GICD_PIDR2_ARCHREV_SHIFT; + vers &= GICD_PIDR2_ARCHREV_MASK; + + if (IS_ENABLED(CFG_ARM_GICV3)) { + assert(vers == 3); + } else { + assert(vers == 2 || vers == 1); gicc_base = core_mmu_get_va(gicc_base_pa, MEM_AREA_IO_SEC, GIC_CPU_REG_SIZE); if (!gicc_base) @@ -231,21 +487,52 @@ static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa) gd->gicc_base = gicc_base; gd->gicd_base = gicd_base; gd->max_it = probe_max_it(gicc_base, gicd_base); +#if defined(CFG_ARM_GICV3) + if (affinity_routing_is_enabled(gd) && gicr_base_pa) + probe_redist_base_addrs(gd->gicr_base, gicr_base_pa); +#endif gd->chip.ops = &gic_ops; if (IS_ENABLED(CFG_DT)) gd->chip.dt_get_irq = gic_dt_get_irq; } -void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) +void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa) { struct gic_data __maybe_unused *gd = &gic_data; size_t __maybe_unused n = 0; - gic_init_base_addr(gicc_base_pa, gicd_base_pa); + gic_init_base_addr(gicc_base_pa, gicd_base_pa, gicr_base_pa); +#if defined(CFG_WITH_ARM_TRUSTED_FW) /* GIC configuration is initialized from TF-A when embedded */ -#ifndef CFG_WITH_ARM_TRUSTED_FW + if (affinity_routing_is_enabled(gd)) { + /* Secure affinity routing enabled */ + vaddr_t gicr_base = get_gicr_base(gd); + + if (gicr_base) { + gd->per_cpu_group_status = io_read32(gicr_base + + GICR_IGROUPR0); + gd->per_cpu_group_modifier = io_read32(gicr_base + + GICR_IGRPMODR0); + } else { + IMSG("GIC redistributor base address not provided"); + IMSG("Assuming default GIC group status and modifier"); + gd->per_cpu_group_status = 0xffff00ff; + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + } + } else { + /* Legacy operation with secure affinity routing disabled */ + gd->per_cpu_group_status = io_read32(gd->gicd_base + + GICD_IGROUPR(0)); + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + } +#else /*!CFG_WITH_ARM_TRUSTED_FW*/ + /* + * Without TF-A, GIC is always configured in for legacy operation + * with secure affinity routing disabled. + */ for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) { /* Disable interrupts */ io_write32(gd->gicd_base + GICD_ICENABLER(n), 0xffffffff); @@ -260,7 +547,10 @@ void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) * ID8-ID15(SGI) for Secure interrupts. * All PPI config as Non-secure interrupts. */ - io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffff00ff); + gd->per_cpu_group_status = 0xffff00ff; + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + io_write32(gd->gicd_base + GICD_IGROUPR(n), + gd->per_cpu_group_status); } else { io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffffffff); } @@ -280,9 +570,9 @@ void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_FIQEN | GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1); io_setbits32(gd->gicd_base + GICD_CTLR, - GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1); + GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1NS); #endif -#endif /*CFG_WITH_ARM_TRUSTED_FW*/ +#endif /*!CFG_WITH_ARM_TRUSTED_FW*/ interrupt_main_init(&gic_data.chip); } @@ -389,34 +679,74 @@ static void gic_it_set_pending(struct gic_data *gd, size_t it) io_write32(gd->gicd_base + GICD_ISPENDR(idx), mask); } +static void assert_cpu_mask_is_valid(uint32_t cpu_mask) +{ + bool __maybe_unused to_others = cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS; + bool __maybe_unused to_current = cpu_mask & ITR_CPU_MASK_TO_THIS_CPU; + bool __maybe_unused to_list = cpu_mask & 0xff; + + /* One and only one of the bit fields shall be non-zero */ + assert(to_others + to_current + to_list == 1); +} + static void gic_it_raise_sgi(struct gic_data *gd __maybe_unused, size_t it, - uint8_t cpu_mask, uint8_t group) + uint32_t cpu_mask, bool ns) { #if defined(CFG_ARM_GICV3) - /* Only support sending SGI to the cores in the same cluster now */ uint32_t mask_id = it & 0xf; - uint32_t mask_cpu = cpu_mask & 0xff; - uint64_t mpidr = read_mpidr(); - uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >> MPIDR_AFF1_SHIFT; - uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >> MPIDR_AFF2_SHIFT; - uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >> MPIDR_AFF3_SHIFT; - uint64_t mask = (mask_cpu | - SHIFT_U64(mask_aff1, 16) | - SHIFT_U64(mask_id, 24) | - SHIFT_U64(mask_aff2, 32) | - SHIFT_U64(mask_aff3, 48)); + uint64_t mask = SHIFT_U64(mask_id, 24); + + assert_cpu_mask_is_valid(cpu_mask); + + if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { + mask |= BIT64(GICC_SGI_IRM_BIT); + } else { + uint64_t mpidr = read_mpidr(); + uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >> + MPIDR_AFF1_SHIFT; + uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >> + MPIDR_AFF2_SHIFT; + uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >> + MPIDR_AFF3_SHIFT; + + mask |= SHIFT_U64(mask_aff1, GICC_SGI_AFF1_SHIFT); + mask |= SHIFT_U64(mask_aff2, GICC_SGI_AFF2_SHIFT); + mask |= SHIFT_U64(mask_aff3, GICC_SGI_AFF3_SHIFT); + + if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { + mask |= BIT32(mpidr & 0xf); + } else { + /* + * Only support sending SGI to the cores in the + * same cluster now. + */ + mask |= cpu_mask & 0xff; + } + } /* Raise the interrupt */ - if (group) + if (ns) write_icc_asgi1r(mask); else write_icc_sgi1r(mask); #else - uint32_t mask_id = it & 0xf; - uint32_t mask_group = group & 0x1; - uint32_t mask_cpu = cpu_mask & 0xff; - uint32_t mask = (mask_id | SHIFT_U32(mask_group, 15) | - SHIFT_U32(mask_cpu, 16)); + uint32_t mask_id = it & GICD_SGIR_SIGINTID_MASK; + uint32_t mask_group = ns; + uint32_t mask = mask_id; + + assert_cpu_mask_is_valid(cpu_mask); + + mask |= SHIFT_U32(mask_group, GICD_SGIR_NSATT_SHIFT); + if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { + mask |= SHIFT_U32(GICD_SGIR_TO_OTHER_CPUS, + GICD_SGIR_TARGET_LIST_FILTER_SHIFT); + } else if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { + mask |= SHIFT_U32(GICD_SGIR_TO_THIS_CPU, + GICD_SGIR_TARGET_LIST_FILTER_SHIFT); + } else { + mask |= SHIFT_U32(cpu_mask & 0xff, + GICD_SGIR_CPU_TARGET_LIST_SHIFT); + } /* Raise the interrupt */ io_write32(gd->gicd_base + GICD_SGIR, mask); @@ -574,22 +904,18 @@ static void gic_op_raise_pi(struct itr_chip *chip, size_t it) } static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, - uint8_t cpu_mask) + uint32_t cpu_mask) { struct gic_data *gd = container_of(chip, struct gic_data, chip); + bool ns = false; assert(gd == &gic_data); /* Should be Software Generated Interrupt */ assert(it < NUM_SGI); - if (it > gd->max_it) - panic(); - - if (it < NUM_NS_SGI) - gic_it_raise_sgi(gd, it, cpu_mask, 1); - else - gic_it_raise_sgi(gd, it, cpu_mask, 0); + ns = BIT32(it) & gd->per_cpu_group_status; + gic_it_raise_sgi(gd, it, cpu_mask, ns); } static void gic_op_set_affinity(struct itr_chip *chip, size_t it, @@ -604,3 +930,64 @@ static void gic_op_set_affinity(struct itr_chip *chip, size_t it, gic_it_set_cpu_mask(gd, it, cpu_mask); } + +#ifdef CFG_DT +/* Callback for "interrupts" and "interrupts-extended" DT node properties */ +static TEE_Result dt_get_gic_chip_cb(struct dt_pargs *arg, void *priv_data, + struct itr_desc *itr_desc) +{ + int itr_num = DT_INFO_INVALID_INTERRUPT; + struct itr_chip *chip = priv_data; + uint32_t phandle_args[2] = { }; + uint32_t type = 0; + uint32_t prio = 0; + + assert(arg && itr_desc); + + /* + * gic_dt_get_irq() expects phandle arguments passed are still in DT + * format (big-endian) whereas struct dt_pargs carries converted + * formats. Therefore swap again phandle arguments. gic_dt_get_irq() + * consumes only the 2 first arguments. + */ + if (arg->args_count < 2) + return TEE_ERROR_GENERIC; + phandle_args[0] = cpu_to_fdt32(arg->args[0]); + phandle_args[1] = cpu_to_fdt32(arg->args[1]); + + itr_num = gic_dt_get_irq((const void *)phandle_args, 2, &type, &prio); + if (itr_num == DT_INFO_INVALID_INTERRUPT) + return TEE_ERROR_GENERIC; + + gic_op_add(chip, itr_num, type, prio); + + itr_desc->chip = chip; + itr_desc->itr_num = itr_num; + + return TEE_SUCCESS; +} + +static TEE_Result gic_probe(const void *fdt, int offs, const void *cd __unused) +{ + if (interrupt_register_provider(fdt, offs, dt_get_gic_chip_cb, + &gic_data.chip)) + panic(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match gic_match_table[] = { + { .compatible = "arm,cortex-a15-gic" }, + { .compatible = "arm,cortex-a7-gic" }, + { .compatible = "arm,cortex-a5-gic" }, + { .compatible = "arm,cortex-a9-gic" }, + { .compatible = "arm,gic-400" }, + { } +}; + +DEFINE_DT_DRIVER(gic_dt_driver) = { + .name = "gic", + .match_table = gic_match_table, + .probe = gic_probe, +}; +#endif /*CFG_DT*/ diff --git a/core/drivers/gpio/gpio.c b/core/drivers/gpio/gpio.c index a3e4f23155da42e246a8dd8b3c6d91b151ff49f8..457599ecd1464e1090c3bbd2c00dbfdf7c3558d0 100644 --- a/core/drivers/gpio/gpio.c +++ b/core/drivers/gpio/gpio.c @@ -32,14 +32,19 @@ TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio) static char *gpio_get_dt_prop_name(const char *gpio_name) { + int ret = 0; char *prop_name = NULL; - int max_len = strlen(gpio_name) + strlen("-gpios") + 1; + size_t max_len = strlen(gpio_name) + strlen("-gpios") + 1; prop_name = calloc(1, max_len); if (!prop_name) return NULL; - snprintf(prop_name, max_len, "%s-gpios", gpio_name); + ret = snprintf(prop_name, max_len, "%s-gpios", gpio_name); + if (ret < 0 || (size_t)ret >= max_len) { + free(prop_name); + return NULL; + } return prop_name; } diff --git a/core/drivers/hisi_trng.c b/core/drivers/hisi_trng.c new file mode 100644 index 0000000000000000000000000000000000000000..3d865e40a85ccac675ddebe6db0bcb2a63c64d19 --- /dev/null +++ b/core/drivers/hisi_trng.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 HiSilicon Limited. */ + +#include <initcall.h> +#include <io.h> +#include <kernel/spinlock.h> +#include <malloc.h> +#include <mm/core_memprot.h> +#include <platform_config.h> +#include <rng_support.h> +#include <string.h> + +#define HTRNG_RANDATA_REG 0xF0 +#define HTRNG_BYTES 4U + +#define POLL_PERIOD 10 +#define POLL_TIMEOUT 1000 + +struct hisi_trng { + vaddr_t base; +}; + +static unsigned int trng_lock = SPINLOCK_UNLOCK; +static struct hisi_trng *trng_dev; + +static TEE_Result trng_read(uint32_t *val) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&trng_lock); + if (IO_READ32_POLL_TIMEOUT(trng_dev->base + HTRNG_RANDATA_REG, + *val, *val, POLL_PERIOD, POLL_TIMEOUT)) { + EMSG("Hardware busy"); + ret = TEE_ERROR_BUSY; + } + cpu_spin_unlock_xrestore(&trng_lock, exceptions); + + return ret; +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t current_len = 0; + uint32_t val = 0; + size_t size = 0; + + if (!trng_dev) { + EMSG("No valid TRNG device"); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (!buf || !len) { + EMSG("Invalid input parameter"); + return TEE_ERROR_BAD_PARAMETERS; + } + + while (current_len < len) { + ret = trng_read(&val); + if (ret) + return TEE_ERROR_BUSY; + + size = MIN(HTRNG_BYTES, len - current_len); + memcpy((uint8_t *)buf + current_len, &val, size); + current_len += size; + } + + return TEE_SUCCESS; +} + +static TEE_Result trng_init(void) +{ + DMSG("TRNG driver init start"); + trng_dev = calloc(1, sizeof(struct hisi_trng)); + if (!trng_dev) { + EMSG("Fail to calloc trng device"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + trng_dev->base = (vaddr_t)phys_to_virt_io(HISI_TRNG_BASE, + HISI_TRNG_SIZE); + if (!trng_dev->base) { + EMSG("Fail to get trng io_base"); + free(trng_dev); + trng_dev = NULL; + return TEE_ERROR_ACCESS_DENIED; + } + + DMSG("TRNG driver init done"); + + return TEE_SUCCESS; +} + +early_init(trng_init); diff --git a/core/drivers/imx_wdog.c b/core/drivers/imx_wdog.c index f1642a238aa7eccdb7b18433ec0675b14c163fae..bdd5f3963e56e919432d3dc64a43685d6de8f540 100644 --- a/core/drivers/imx_wdog.c +++ b/core/drivers/imx_wdog.c @@ -47,7 +47,7 @@ void imx_wdog_restart(bool external_reset __maybe_unused) uint32_t val = 0; if (!wdog_base) { - EMSG("No wdog mapped\n"); + EMSG("No wdog mapped"); panic(); } @@ -67,7 +67,7 @@ void imx_wdog_restart(bool external_reset __maybe_unused) else val = 0x24; - DMSG("val %x\n", val); + DMSG("val %x", val); io_write16(wdog_base + WDT_WCR, val); dsb(); @@ -105,7 +105,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) fdt = get_dt(); if (!fdt) { - EMSG("No DTB\n"); + EMSG("No DTB"); return TEE_ERROR_NOT_SUPPORTED; } @@ -131,7 +131,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) } if (!found_off) { - EMSG("No Watchdog found in DTB\n"); + EMSG("No Watchdog found in DTB"); return TEE_ERROR_ITEM_NOT_FOUND; } @@ -139,7 +139,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) "fsl,ext-reset-output"); if (dt_map_dev(fdt, found_off, &vbase, &sz, DT_MAP_AUTO) < 0) { - EMSG("Failed to map Watchdog\n"); + EMSG("Failed to map Watchdog"); return TEE_ERROR_ITEM_NOT_FOUND; } diff --git a/core/drivers/ls_dspi.c b/core/drivers/ls_dspi.c index a7055e09dd85e5aee044fd885f88287da0a09e98..23942aa0adcffc7ccd6a503b0489f191cdfca42e 100644 --- a/core/drivers/ls_dspi.c +++ b/core/drivers/ls_dspi.c @@ -547,7 +547,7 @@ static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data) */ fdt = get_dt(); if (!fdt) { - EMSG("Unable to get DTB, DSPI init failed\n"); + EMSG("Unable to get DTB, DSPI init failed"); return TEE_ERROR_ITEM_NOT_FOUND; } diff --git a/core/drivers/ls_gpio.c b/core/drivers/ls_gpio.c index 5d4a297dcd9312b48c5873c144e8258c79830bef..27a735207f9d88da903e3c91b23c82a5f7c6d3ef 100644 --- a/core/drivers/ls_gpio.c +++ b/core/drivers/ls_gpio.c @@ -187,7 +187,7 @@ static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data) */ fdt = get_embedded_dt(); if (!fdt) { - EMSG("Unable to get the Embedded DTB, GPIO init failed\n"); + EMSG("Unable to get the Embedded DTB, GPIO init failed"); return TEE_ERROR_GENERIC; } diff --git a/core/drivers/ls_i2c.c b/core/drivers/ls_i2c.c index 87d73815fe8fcd9d66d19ee376d1b5986ccb98dc..91df01385a16cede3d55885812f6771950ad827b 100644 --- a/core/drivers/ls_i2c.c +++ b/core/drivers/ls_i2c.c @@ -132,7 +132,7 @@ TEE_Result i2c_init(struct ls_i2c_data *i2c_data) */ fdt = get_embedded_dt(); if (!fdt) { - EMSG("Unable to get the Embedded DTB, I2C init failed\n"); + EMSG("Unable to get the Embedded DTB, I2C init failed"); return TEE_ERROR_GENERIC; } diff --git a/core/drivers/nvmem/atmel_sfc.c b/core/drivers/nvmem/atmel_sfc.c new file mode 100644 index 0000000000000000000000000000000000000000..e034aa706201e2bb3ad0a7dbf9e05f653e61db46 --- /dev/null +++ b/core/drivers/nvmem/atmel_sfc.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include <drivers/nvmem.h> +#include <io.h> +#include <kernel/dt_driver.h> +#include <malloc.h> +#include <matrix.h> +#include <sama5d2.h> +#include <string.h> +#include <tee_api_defines.h> +#include <tee_api_types.h> +#include <types_ext.h> + +#define ATMEL_SFC_KR 0x0 +#define ATMEL_SFC_SR 0x1C +#define ATMEL_SFC_SR_PGMC BIT(0) +#define ATMEL_SFC_SR_PGMF BIT(1) +#define ATMEL_SFC_DR 0x20 + +#define ATMEL_SFC_CELLS_32 17 +#define ATMEL_SFC_CELLS_8 (ATMEL_SFC_CELLS_32 * sizeof(uint32_t)) + +struct atmel_sfc { + vaddr_t base; + uint8_t fuses[ATMEL_SFC_CELLS_8]; +}; + +static TEE_Result atmel_sfc_read_cell(struct nvmem_cell *cell, uint8_t *data) +{ + struct atmel_sfc *atmel_sfc = cell->drv_data; + + memcpy(data, &atmel_sfc->fuses[cell->offset], cell->len); + + return TEE_SUCCESS; +} + +static void atmel_sfc_put_cell(struct nvmem_cell *cell) +{ + free(cell); +} + +static const struct nvmem_ops atmel_sfc_nvmem_ops = { + .read_cell = atmel_sfc_read_cell, + .put_cell = atmel_sfc_put_cell, +}; + +static TEE_Result atmel_sfc_dt_get(struct dt_pargs *args, + void *data, struct nvmem_cell **out_cell) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvmem_cell *cell = NULL; + + /* Freed from atmel_sfc_put_cell() */ + cell = calloc(1, sizeof(*cell)); + if (!cell) + return TEE_ERROR_OUT_OF_MEMORY; + + res = nvmem_cell_parse_dt(args->fdt, args->phandle_node, cell); + if (res) + goto out_free; + + if (cell->offset + cell->len > ATMEL_SFC_CELLS_8) { + res = TEE_ERROR_GENERIC; + goto out_free; + } + + cell->ops = &atmel_sfc_nvmem_ops; + cell->drv_data = data; + *out_cell = cell; + + return TEE_SUCCESS; + +out_free: + free(cell); + + return res; +} + +static void atmel_sfc_read_fuse(struct atmel_sfc *atmel_sfc) +{ + size_t i = 0; + uint32_t val = 0; + + for (i = 0; i < ATMEL_SFC_CELLS_32; i++) { + val = io_read32(atmel_sfc->base + ATMEL_SFC_DR + i * 4); + memcpy(&atmel_sfc->fuses[i * 4], &val, sizeof(val)); + } +} + +static TEE_Result atmel_sfc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + vaddr_t base = 0; + size_t size = 0; + struct atmel_sfc *atmel_sfc = NULL; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_NODE_DISABLED; + + matrix_configure_periph_secure(AT91C_ID_SFC); + + if (dt_map_dev(fdt, node, &base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + atmel_sfc = calloc(1, sizeof(*atmel_sfc)); + if (!atmel_sfc) + return TEE_ERROR_OUT_OF_MEMORY; + + atmel_sfc->base = base; + + atmel_sfc_read_fuse(atmel_sfc); + + return nvmem_register_provider(fdt, node, atmel_sfc_dt_get, atmel_sfc); +} + +static const struct dt_device_match atmel_sfc_match_table[] = { + { .compatible = "atmel,sama5d2-sfc" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_sfc_dt_driver) = { + .name = "atmel_sfc", + .type = DT_DRIVER_NVMEM, + .match_table = atmel_sfc_match_table, + .probe = atmel_sfc_probe, +}; diff --git a/core/drivers/nvmem/nvmem.c b/core/drivers/nvmem/nvmem.c new file mode 100644 index 0000000000000000000000000000000000000000..7d30c2c166d69c10862625a24a6880bc7dc9a88b --- /dev/null +++ b/core/drivers/nvmem/nvmem.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Microchip + */ + +#include <drivers/nvmem.h> +#include <kernel/dt.h> +#include <libfdt.h> + +TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, + struct nvmem_cell *cell) +{ + size_t buf_len = 0; + paddr_t offset = 0; + + buf_len = fdt_reg_size(fdt, nodeoffset); + if (buf_len == DT_INFO_INVALID_REG_SIZE) + return TEE_ERROR_GENERIC; + + offset = fdt_reg_base_address(fdt, nodeoffset); + if (offset == DT_INFO_INVALID_REG) + return TEE_ERROR_GENERIC; + + cell->len = buf_len; + cell->offset = offset; + + return TEE_SUCCESS; +} + +TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, + const char *name, struct nvmem_cell **cell) +{ + int index = 0; + + index = fdt_stringlist_search(fdt, nodeoffset, "nvmem-cell-names", + name); + if (index < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + return nvmem_get_cell_by_index(fdt, nodeoffset, index, cell); +} + +TEE_Result nvmem_get_cell_by_index(const void *fdt, + int nodeoffset, + unsigned int index, + struct nvmem_cell **out_cell) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *cell = NULL; + + res = dt_driver_device_from_node_idx_prop("nvmem-cells", fdt, + nodeoffset, index, + DT_DRIVER_NVMEM, &cell); + if (!res) + *out_cell = cell; + + return res; +} + +TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, + uint8_t **out_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!cell->ops->read_cell) + return TEE_ERROR_NOT_SUPPORTED; + + *out_data = malloc(cell->len); + if (!out_data) + return TEE_ERROR_OUT_OF_MEMORY; + + res = cell->ops->read_cell(cell, *out_data); + if (res) + free(*out_data); + + return res; +} diff --git a/core/drivers/nvmem/sub.mk b/core/drivers/nvmem/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..cec703b14ffb8e49c21ae4e282197c72ede540e9 --- /dev/null +++ b/core/drivers/nvmem/sub.mk @@ -0,0 +1,2 @@ +srcs-y += nvmem.c +srcs-$(CFG_ATMEL_SFC) += atmel_sfc.c diff --git a/core/drivers/plic.c b/core/drivers/plic.c index be14656f08c65e78bfb8ad7cd67a4e06472f5f5b..3356dacb8feef97e5b602becee80288dc698504d 100644 --- a/core/drivers/plic.c +++ b/core/drivers/plic.c @@ -197,7 +197,7 @@ static void plic_op_raise_pi(struct itr_chip *chip, size_t it) } static void plic_op_raise_sgi(struct itr_chip *chip __unused, - size_t it __unused, uint8_t cpu_mask __unused) + size_t it __unused, uint32_t cpu_mask __unused) { } @@ -275,7 +275,7 @@ void plic_it_handle(void) struct plic_data *pd = &plic_data; uint32_t id = plic_claim_interrupt(pd); - if (id <= pd->max_it) + if (id > 0 && id <= pd->max_it) interrupt_call_handlers(&pd->chip, id); else DMSG("ignoring interrupt %" PRIu32, id); diff --git a/core/drivers/regulator/regulator.c b/core/drivers/regulator/regulator.c index 247e2313dc8e7fca7b19c4370d173d439fd6c7fb..4691913062b6dd41ab797afeeab6bb53cbc01b51 100644 --- a/core/drivers/regulator/regulator.c +++ b/core/drivers/regulator/regulator.c @@ -213,21 +213,29 @@ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv) } TEE_Result regulator_supported_voltages(struct regulator *regulator, - struct regulator_voltages **voltages) + struct regulator_voltages_desc **desc, + const int **levels) { - assert(regulator && voltages); + assert(regulator && desc && levels); if (regulator->ops->supported_voltages) { TEE_Result res = TEE_ERROR_GENERIC; - res = regulator->ops->supported_voltages(regulator, voltages); - if (res == TEE_SUCCESS) - return TEE_SUCCESS; + res = regulator->ops->supported_voltages(regulator, desc, + levels); if (res != TEE_ERROR_NOT_SUPPORTED) return res; + } else { + *desc = ®ulator->voltages_fallback.desc; + *levels = regulator->voltages_fallback.levels; } - *voltages = ®ulator->voltages_fallback.desc; + assert(((*desc)->type == VOLTAGE_TYPE_FULL_LIST && + (*levels)[0] >= regulator->min_uv && (*desc)->num_levels && + (*levels)[(*desc)->num_levels - 1] <= regulator->max_uv) || + ((*desc)->type == VOLTAGE_TYPE_INCREMENT && + (*levels)[0] >= regulator->min_uv && + (*levels)[1] <= regulator->max_uv)); return TEE_SUCCESS; } @@ -287,26 +295,6 @@ TEE_Result regulator_register(struct regulator *regulator) return TEE_SUCCESS; } -/* - * Log regulators state - */ -void regulator_print_state(const char *message __maybe_unused) -{ - struct regulator *regulator = NULL; - - DMSG("Regulator state: %s", message); - DMSG("name use\ten\tuV\tmin\tmax\tflags\tsupply"); - - SLIST_FOREACH(regulator, ®ulator_device_list, link) - DMSG("%8s %u\t%d\t%d\t%d\t%d\t%#x\t%s\n", - regulator->name, regulator->refcount, - regulator_is_enabled(regulator), - regulator_get_voltage(regulator), - regulator->min_uv, regulator->max_uv, regulator->flags, - regulator->supply ? regulator_name(regulator->supply) : - "<none>"); -} - /* * Clean-up regulators that are not used. */ @@ -323,9 +311,187 @@ static TEE_Result regulator_core_cleanup(void) } } - regulator_print_state(__func__); + regulator_print_tree(); return TEE_SUCCESS; } release_init_resource(regulator_core_cleanup); + +/* Return updated message buffer position of NULL on failure */ +static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) +{ + va_list ap = { }; + int max_len = end - cur; + int ret = 0; + + va_start(ap, fmt); + ret = vsnprintf(cur, max_len, fmt, ap); + va_end(ap); + + if (ret < 0 || ret >= max_len) + return NULL; + + return cur + ret; +} + +static struct regulator *find_next_regulator(struct regulator *parent, + struct regulator *sibling) +{ + struct regulator *regulator = NULL; + + if (sibling) + regulator = SLIST_NEXT(sibling, link); + else + regulator = SLIST_FIRST(®ulator_device_list); + + while (regulator && regulator->supply != parent) + regulator = SLIST_NEXT(regulator, link); + + return regulator; +} + +/* Regulator is the last supplied one by its supply in the registered list */ +static bool regulator_is_supply_last_supplied(struct regulator *regulator) +{ + return !find_next_regulator(regulator->supply, regulator); +} + +/* Supply last node may already be printed for indentation level @cur_indent */ +static bool indent_with_empty_string(struct regulator *node_regulator, + int node_indent, int cur_indent) +{ + struct regulator *r = node_regulator; + int n = 0; + + /* Find supply at indentation level @node_indent - @cur_indent - 1 */ + for (n = 0; n < node_indent - cur_indent - 1; n++) + r = r->supply; + + return regulator_is_supply_last_supplied(r); +} + +static void __maybe_unused print_regulator(struct regulator *regulator, + int indent) +{ + static const char * const level_unit[] = { "uV", "mV", "V" }; + int max_unit = ARRAY_SIZE(level_unit); + int level_max = 0; + int level_min = 0; + int level_cur = 0; + char msg_buf[128] = { }; + char *msg_end = msg_buf + sizeof(msg_buf); + char *msg = msg_buf; + int n_max = 0; + int n_min = 0; + int n_cur = 0; + int n = 0; + + if (indent) { + /* Indent for root clock level */ + msg = add_msg(msg, msg_end, " "); + if (!msg) + goto out; + + /* Indent for root supply to regulator supply levels */ + for (n = 0; n < indent - 1; n++) { + if (indent_with_empty_string(regulator, indent, n)) + msg = add_msg(msg, msg_end, " "); + else + msg = add_msg(msg, msg_end, "| "); + if (!msg) + goto out; + } + + /* Regulator indentation */ + if (regulator_is_supply_last_supplied(regulator)) + msg = add_msg(msg, msg_end, "`-- "); + else + msg = add_msg(msg, msg_end, "|-- "); + + if (!msg) + goto out; + } else { + /* Root supply indentation */ + msg = add_msg(msg, msg_end, "o- "); + } + + regulator_get_range(regulator, &level_min, &level_max); + level_cur = regulator_get_voltage(regulator); + + for (n_cur = 1; !(level_cur % 1000) && n_cur < max_unit; n_cur++) + level_cur /= 1000; + for (n_max = 1; !(level_max % 1000) && n_max < max_unit; n_max++) + level_max /= 1000; + for (n_min = 1; !(level_min % 1000) && n_min < max_unit; n_min++) + level_min /= 1000; + + msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / flags %#"PRIx32 + " / %d %s ", regulator_name(regulator), + regulator_is_enabled(regulator) ? "on " : "off", + regulator->refcount, regulator->flags, + level_cur, level_unit[n_cur - 1]); + if (!msg) + goto out; + + if (level_min == level_max) + msg = add_msg(msg, msg_end, "fixed)"); + else if (level_max == INT_MAX) + msg = add_msg(msg, msg_end, "[%d %s .. MAX])", + level_min, level_unit[n_min - 1]); + else + msg = add_msg(msg, msg_end, "[%d %s .. %d %s])", + level_min, level_unit[n_min - 1], + level_max, level_unit[n_max - 1]); + +out: + if (!msg) + snprintf(msg_end - 4, 4, "..."); + + DMSG("%s", msg_buf); +} + +static void print_tree(void) +{ + struct regulator *regulator = NULL; + struct regulator *parent = NULL; + struct regulator *next = NULL; + int indent = -1; + + while (true) { + next = find_next_regulator(parent, regulator); + if (next) { + print_regulator(next, indent + 1); + /* Enter the subtree of the next regulator */ + parent = next; + indent++; + regulator = NULL; + } else { + /* + * We've processed all children at this level. + * If parent is NULL we're at the top and are done. + */ + if (!parent) + break; + /* + * Move up one level to resume with the next + * regulator of the parent. + */ + regulator = parent; + parent = regulator->supply; + indent--; + } + } +} + +void regulator_print_tree(void) +{ + if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) && + TRACE_LEVEL >= TRACE_DEBUG) { + DMSG("Regulator tree summary"); + if (SLIST_EMPTY(®ulator_device_list)) + DMSG("-- No registered regulator"); + else + print_tree(); + } +} diff --git a/core/drivers/regulator/regulator_gpio.c b/core/drivers/regulator/regulator_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..a5fa4c28ebbfe32ff477eb3d993bc418037ed5d1 --- /dev/null +++ b/core/drivers/regulator/regulator_gpio.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include <assert.h> +#include <compiler.h> +#include <drivers/gpio.h> +#include <drivers/regulator.h> +#include <dt-bindings/gpio/gpio.h> +#include <kernel/delay.h> +#include <libfdt.h> +#include <trace.h> + +static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0); + +/* + * struct regulator_gpio - GPIO controlled regulator + * @regulator: Preallocated regulator instance + * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on + * @enable_delay: Time (in microsecond) for the regulator to get enabled + * @voltage_gpio: GPIO for the voltage level selection + * @voltage_levels_uv: 2 cells array supported voltage levels, increasing order + * @voltage_level_high: True if higher voltage level relates to active high GPIO + */ +struct regulator_gpio { + struct regulator regulator; + struct gpio *enable_gpio; + unsigned int enable_delay; + struct gpio *voltage_gpio; + int voltage_levels_uv[2]; + bool voltage_level_high; +}; + +static struct regulator_gpio *regulator_priv(struct regulator *regulator) +{ + return container_of(regulator, struct regulator_gpio, regulator); +} + +static TEE_Result regulator_gpio_set_state(struct regulator *regulator, + bool enabled) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + if (regu->enable_gpio) { + if (enabled) { + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH); + if (regu->enable_delay) + udelay(regu->enable_delay); + } else { + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW); + } + } + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_read_state(struct regulator *regulator, + bool *enabled) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + if (regu->enable_gpio) + *enabled = gpio_get_value(regu->enable_gpio); + else + *enabled = true; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_set_voltage(struct regulator *regulator, + int level_uv) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + if (level_uv == regu->voltage_levels_uv[0]) + gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_LOW); + else if (level_uv == regu->voltage_levels_uv[1]) + gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_HIGH); + else + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_read_voltage(struct regulator *regulator, + int *level_uv) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + *level_uv = regu->voltage_levels_uv[gpio_get_value(regu->voltage_gpio)]; + + return TEE_SUCCESS; +} + +static const struct regulator_ops regulator_gpio_ops = { + .set_state = regulator_gpio_set_state, + .get_state = regulator_gpio_read_state, + .set_voltage = regulator_gpio_set_voltage, + .get_voltage = regulator_gpio_read_voltage, +}; + +static TEE_Result get_enable_gpio(const void *fdt, int node, + struct regulator_gpio *regu) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct gpio *gpio = NULL; + + res = gpio_dt_get_by_index(fdt, node, 0, "enable", &gpio); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + regu->enable_gpio = NULL; + + return TEE_SUCCESS; + } + if (res) + return res; + + /* Override active level phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "enable-active-high")) + gpio->dt_flags &= ~GPIO_ACTIVE_LOW; + else + gpio->dt_flags |= GPIO_ACTIVE_LOW; + + /* Override open drain/open source phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "gpio-open-drain")) + gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN; + else + gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN; + + cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL); + if (cuint) + regu->enable_delay = fdt32_to_cpu(*cuint); + + gpio_set_direction(gpio, GPIO_DIR_OUT); + + regu->enable_gpio = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result get_voltage_level_gpio(const void *fdt, int node, + struct regulator_gpio *regu) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct gpio *gpio = NULL; + void *gpio_ref = &gpio; + int len = 0; + + res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0, + DT_DRIVER_GPIO, gpio_ref); + if (res) + return res; + + /* + * DT bindings allows more than 1 GPIO to control more than + * 2 voltage levels. As it's not used so far in known platforms + * this implementation is simplified to support only 2 voltage + * levels controlled with a single GPIO. + */ + if (dt_driver_device_from_node_idx_prop("gpios", fdt, node, 1, + DT_DRIVER_GPIO, gpio_ref) != + TEE_ERROR_ITEM_NOT_FOUND) { + EMSG("Multiple GPIOs not supported for level control"); + return TEE_ERROR_GENERIC; + } + + cuint = fdt_getprop(fdt, node, "states", &len); + if (!cuint || len != 4 * sizeof(fdt32_t)) { + EMSG("Node %s expects 2 levels from property \"states\"", + fdt_get_name(fdt, node, NULL)); + return TEE_ERROR_GENERIC; + } + + if (fdt32_to_cpu(*(cuint + 1))) { + assert(!fdt32_to_cpu(*(cuint + 3))); + regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint + 2)); + regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint)); + } else { + assert(fdt32_to_cpu(*(cuint + 3)) == 1); + regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint)); + regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint + 2)); + regu->voltage_level_high = true; + } + + gpio_set_direction(gpio, GPIO_DIR_OUT); + + regu->voltage_gpio = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct regulator_gpio *regu = NULL; + struct regu_dt_desc desc = { }; + const char *supply_name = NULL; + const char *type = NULL; + char *regu_name = NULL; + + regu_name = (char *)fdt_get_name(fdt, node, NULL); + + type = fdt_getprop(fdt, node, "regulator-type", NULL); + if (type && strcmp(type, "voltage")) { + EMSG("Regulator node %s: type \"%s\" not supported", + regu_name, type); + res = TEE_ERROR_GENERIC; + goto err; + } + + regu = calloc(1, sizeof(*regu)); + if (!regu) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + res = get_enable_gpio(fdt, node, regu); + if (res) + goto err; + + res = get_voltage_level_gpio(fdt, node, regu); + if (res) + goto err; + + if (fdt_getprop(fdt, node, "vin-supply", NULL)) + supply_name = "vin"; + + desc = (struct regu_dt_desc){ + .name = regu_name, + .ops = ®ulator_gpio_ops, + .supply_name = supply_name, + .regulator = ®u->regulator, + }; + + res = regulator_dt_register(fdt, node, node, &desc); + if (res) { + EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res); + goto err; + } + + return TEE_SUCCESS; + +err: + free(regu); + + return res; +} + +static const struct dt_device_match regulator_gpio_match_table[] = { + { .compatible = "regulator-gpio" }, + { } +}; + +DEFINE_DT_DRIVER(regulator_gpio_dt_driver) = { + .name = "regulator-gpio", + .match_table = regulator_gpio_match_table, + .probe = regulator_gpio_probe, +}; diff --git a/core/drivers/regulator/stm32_vrefbuf.c b/core/drivers/regulator/stm32_vrefbuf.c index fc2b6387db2fda5d18ae5fbe4c4d28d2d32def3f..18ccb099b014239954bccd8fb0e2dd77f85f1c7b 100644 --- a/core/drivers/regulator/stm32_vrefbuf.c +++ b/core/drivers/regulator/stm32_vrefbuf.c @@ -49,7 +49,8 @@ struct vrefbuf_compat { * @regulator: Preallocated instance for the regulator * @compat: Compatibility data * @voltages_desc: Supported voltage level description - * @voltages_level: Supplorted levels, must follow @voltages_desc + * @voltages_level: Supplorted levels description + * @voltages_start_index: start index in compat for supported levels */ struct vrefbuf_regul { vaddr_t base; @@ -57,8 +58,8 @@ struct vrefbuf_regul { uint64_t disable_timeout; struct regulator regulator; const struct vrefbuf_compat *compat; - struct regulator_voltages voltages_desc; - int supported_levels[VREFBUF_LEVELS_COUNT]; + struct regulator_voltages_desc voltages_desc; + size_t voltages_start_index; }; static const struct vrefbuf_compat stm32mp15_vrefbuf_compat = { @@ -207,41 +208,47 @@ static TEE_Result vrefbuf_set_voltage(struct regulator *regulator, int level_uv) } static TEE_Result vrefbuf_list_voltages(struct regulator *regulator __unused, - struct regulator_voltages **voltages) + struct regulator_voltages_desc **desc, + const int **levels) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); + const int *levels_ref = vr->compat->voltages; - if (!vr->voltages_desc.type) { - size_t num_levels = ARRAY_SIZE(vr->compat->voltages); - unsigned int index_high = num_levels - 1; - unsigned int index_low = 0; - unsigned int count = 0; - unsigned int n = 0; - - for (n = 0; n <= index_high; n++) - if (vr->compat->voltages[n] >= regulator->min_uv) - break; - if (n > index_high) - return TEE_ERROR_GENERIC; - index_low = n; + *desc = &vr->voltages_desc; + *levels = levels_ref + vr->voltages_start_index; - for (n = index_high; n >= index_low; n--) - if (vr->compat->voltages[n] <= regulator->max_uv) - break; - if (n < index_low) - return TEE_ERROR_GENERIC; - index_high = n; + return TEE_SUCCESS; +} - count = index_high - index_low + 1; +static TEE_Result set_voltages_desc(struct regulator *regulator) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + size_t num_levels = ARRAY_SIZE(vr->compat->voltages); + int index_high = num_levels - 1; + int index_low = 0; + int n = 0; - vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; - vr->voltages_desc.num_levels = count; - for (n = 0; n < count; n++) - vr->supported_levels[n] = - vr->compat->voltages[index_low + n]; - } + vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; - *voltages = &vr->voltages_desc; + for (n = 0; n <= index_high; n++) + if (vr->compat->voltages[n] >= regulator->min_uv) + break; + if (n > index_high) + return TEE_ERROR_GENERIC; + index_low = n; + + for (n = index_high; n >= index_low; n--) + if (vr->compat->voltages[n] <= regulator->max_uv) + break; + if (n < index_low) + return TEE_ERROR_GENERIC; + index_high = n; + + assert(index_high - index_low + 1 >= 0 && index_low >= 0); + + vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; + vr->voltages_desc.num_levels = index_high - index_low + 1; + vr->voltages_start_index = index_low; return TEE_SUCCESS; } @@ -289,6 +296,12 @@ static TEE_Result stm32_vrefbuf_init(struct regulator *regulator, const void *fdt __unused, int node __unused) { + TEE_Result res = TEE_ERROR_GENERIC; + + res = set_voltages_desc(regulator); + if (res) + return res; + register_pm_driver_cb(stm32_vrefbuf_pm, regulator, "stm32-vrefbuf"); return TEE_SUCCESS; diff --git a/core/drivers/regulator/stm32mp13_regulator_iod.c b/core/drivers/regulator/stm32mp13_regulator_iod.c new file mode 100644 index 0000000000000000000000000000000000000000..a678d51468dc46d4f15c1dccfd9de07027c57332 --- /dev/null +++ b/core/drivers/regulator/stm32mp13_regulator_iod.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, STMicroelectronics + */ + +#include <assert.h> +#include <compiler.h> +#include <drivers/regulator.h> +#include <drivers/stm32mp1_pwr.h> +#include <drivers/stm32mp1_syscfg.h> +#include <drivers/stm32mp13_regulator_iod.h> +#include <initcall.h> +#include <io.h> +#include <kernel/boot.h> +#include <kernel/dt.h> +#include <kernel/panic.h> +#include <kernel/pm.h> +#include <libfdt.h> +#include <stdint.h> +#include <stdio.h> +#include <stm32_util.h> +#include <trace.h> + +#define TIMEOUT_US_10MS U(10000) + +#define IO_VOLTAGE_THRESHOLD_UV 2700000 + +/* + * struct iod_regul - IO domain regulator instance + * + * @enable_reg: PWR register offset for the IO domain + * @enable_mask: Domain enable register bit mask in PWR register + * @ready_mask: Domain ready bit mask in PWR register + * @valid_mask: Domain valid bit mask in PWR register + * @hslv_id: ID of the related HSLV domain + * @io_comp_id: ID of the related IO compensation domain + * @suspend_state: True if regulator is enabled before suspend, false otherwise + * @suspend_level_uv: Voltage level before suspend, in microvolts + */ +struct iod_regul { + uint32_t enable_reg; + uint32_t enable_mask; + uint32_t ready_mask; + uint32_t valid_mask; + enum stm32mp13_hslv_id hslv_id; + enum stm32mp13_vddsd_comp_id io_comp_id; + bool suspend_state; + int suspend_level_uv; +}; + +static struct iod_regul iod_regulator_priv[IOD_REGU_COUNT] = { + [IOD_SDMMC1] = { + .enable_reg = PWR_CR3_OFF, + .enable_mask = PWR_CR3_VDDSD1EN, + .ready_mask = PWR_CR3_VDDSD1RDY, + .valid_mask = PWR_CR3_VDDSD1VALID, + .hslv_id = SYSCFG_HSLV_IDX_SDMMC1, + .io_comp_id = SYSCFG_IO_COMP_IDX_SD1, + }, + [IOD_SDMMC2] = { + .enable_reg = PWR_CR3_OFF, + .enable_mask = PWR_CR3_VDDSD2EN, + .ready_mask = PWR_CR3_VDDSD2RDY, + .valid_mask = PWR_CR3_VDDSD2VALID, + .hslv_id = SYSCFG_HSLV_IDX_SDMMC2, + .io_comp_id = SYSCFG_IO_COMP_IDX_SD2, + }, +}; + +static struct regulator *iod_regulator[IOD_REGU_COUNT]; + +struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index) +{ + assert(index >= IOD_SDMMC1 && index < IOD_REGU_COUNT); + + return iod_regulator[index]; +} + +static TEE_Result iod_set_state(struct regulator *regu, bool enable) +{ + struct iod_regul *iod = regu->priv; + uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; + + FMSG("%s: set state %u", regulator_name(regu), enable); + + if (enable) { + uint32_t value = 0; + + io_setbits32(pwr_reg, iod->enable_mask); + + if (IO_READ32_POLL_TIMEOUT(pwr_reg, value, + value & iod->ready_mask, + 0, TIMEOUT_US_10MS)) + return TEE_ERROR_GENERIC; + + io_setbits32(pwr_reg, iod->valid_mask); + io_clrbits32(pwr_reg, iod->enable_mask); + + stm32mp_set_vddsd_comp_state(iod->io_comp_id, true); + } else { + stm32mp_set_vddsd_comp_state(iod->io_comp_id, false); + + io_clrbits32(pwr_reg, iod->enable_mask | iod->valid_mask); + } + + return TEE_SUCCESS; +} + +static TEE_Result iod_get_state(struct regulator *regu, bool *enabled) +{ + struct iod_regul *iod = regu->priv; + uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; + + *enabled = io_read32(pwr_reg) & (iod->enable_mask | iod->valid_mask); + + return TEE_SUCCESS; +} + +static TEE_Result iod_get_voltage(struct regulator *regu, int *level_uv) +{ + *level_uv = regulator_get_voltage(regu->supply); + + return TEE_SUCCESS; +} + +static TEE_Result iod_set_voltage(struct regulator *regu, int level_uv) +{ + struct iod_regul *iod = regu->priv; + TEE_Result res = TEE_ERROR_GENERIC; + bool iod_enabled = false; + + FMSG("%s: set voltage level to %duV", regulator_name(regu), level_uv); + + res = iod_get_state(regu, &iod_enabled); + if (res) + return res; + + /* Isolate IOs and disable IOs compensation when changing voltage */ + if (iod_enabled) { + res = iod_set_state(regu, false); + if (res) + return res; + } + + /* + * Set IO to low speed. + * Setting high voltage with IOs in high speed mode may damage the IOs. + */ + stm32mp_set_hslv_state(iod->hslv_id, false); + + /* Forward set voltage request to the power supply */ + res = regulator_set_voltage(regu->supply, level_uv); + if (res) { + EMSG("regulator %s set voltage failed: %#"PRIx32, + regulator_name(regu), res); + + /* Ensure IO domain consistency for current voltage level */ + level_uv = regulator_get_voltage(regu->supply); + } + + if (level_uv <= IO_VOLTAGE_THRESHOLD_UV) + stm32mp_set_hslv_state(iod->hslv_id, true); + + if (iod_enabled) { + TEE_Result res2 = TEE_ERROR_GENERIC; + + res2 = iod_set_state(regu, true); + if (res2) + return res2; + } + + return res; +} + +static TEE_Result iod_list_voltages(struct regulator *regu, + struct regulator_voltages_desc **desc, + const int **levels) +{ + /* Return supply voltage list */ + return regulator_supported_voltages(regu->supply, desc, levels); +} + +/* + * To protect the IOs, we disable High Speed Low Voltage mode before + * entering suspend state and restore the configuration when resuming. + */ +static TEE_Result iod_pm(enum pm_op op, unsigned int pm_hint __unused, + const struct pm_callback_handle *hdl) +{ + struct regulator *regu = hdl->handle; + struct iod_regul *iod = regu->priv; + TEE_Result res = TEE_ERROR_GENERIC; + + assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); + + if (op == PM_OP_SUSPEND) { + FMSG("%s: suspend", regulator_name(regu)); + + res = iod_get_state(regu, &iod->suspend_state); + if (res) + return res; + + res = iod_get_voltage(regu, &iod->suspend_level_uv); + if (res) + return res; + + stm32mp_set_hslv_state(iod->hslv_id, false); + } else { + FMSG("%s: resume", regulator_name(regu)); + + res = iod_set_voltage(regu, iod->suspend_level_uv); + if (res) + return res; + + res = iod_set_state(regu, iod->suspend_state); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result iod_supplied_init(struct regulator *regu, + const void *fdt __unused, int node __unused) +{ + struct iod_regul *iod = regu->priv; + int index = iod - iod_regulator_priv; + + assert(index >= 0 && index < IOD_REGU_COUNT); + + if (regulator_get_voltage(regu) < IO_VOLTAGE_THRESHOLD_UV) + stm32mp_set_hslv_state(iod->hslv_id, true); + + /* Save regulator reference */ + iod_regulator[index] = regu; + + register_pm_driver_cb(iod_pm, regu, "iod-regulator"); + + FMSG("IOD regulator %s intiialized", regulator_name(regu)); + + return TEE_SUCCESS; +} + +static const struct regulator_ops iod_ops = { + .set_state = iod_set_state, + .get_state = iod_get_state, + .set_voltage = iod_set_voltage, + .get_voltage = iod_get_voltage, + .supported_voltages = iod_list_voltages, + .supplied_init = iod_supplied_init, +}; + +#define DEFINE_REG(_id, _name, _supply_name) { \ + .name = (_name), \ + .ops = &iod_ops, \ + .priv = iod_regulator_priv + (_id), \ + .supply_name = (_supply_name), \ +} + +static struct regu_dt_desc iod_regul_desc[IOD_REGU_COUNT] = { + [IOD_SDMMC1] = DEFINE_REG(IOD_SDMMC1, "sdmmc1_io", "vddsd1"), + [IOD_SDMMC2] = DEFINE_REG(IOD_SDMMC2, "sdmmc2_io", "vddsd2"), +}; + +static TEE_Result iod_regulator_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + const char *node_name = NULL; + size_t i = 0; + + node_name = fdt_get_name(fdt, node, NULL); + + FMSG("iod probe node '%s'", node_name); + + /* Look up matching regulator name defined in SoC DTSI file */ + for (i = 0; i < IOD_REGU_COUNT; i++) + if (!strcmp(iod_regul_desc[i].name, node_name)) + break; + + if (i == IOD_REGU_COUNT) { + EMSG("Unexpected IO domain node name '%s'", node_name); + return TEE_ERROR_GENERIC; + } + + return regulator_dt_register(fdt, node, node, iod_regul_desc + i); +} + +static const struct dt_device_match iod_regulator_match_table[] = { + { .compatible = "st,stm32mp13-iod" }, + { } +}; + +DEFINE_DT_DRIVER(stm32mp13_regulator_iod_dt_driver) = { + .name = "stm32mp13-iod-regulator", + .match_table = iod_regulator_match_table, + .probe = iod_regulator_probe, +}; diff --git a/core/drivers/regulator/sub.mk b/core/drivers/regulator/sub.mk index 1562241c794192408024657f130871fbf5244095..82d839a436c773fea20a81af66d13084525af902 100644 --- a/core/drivers/regulator/sub.mk +++ b/core/drivers/regulator/sub.mk @@ -1,4 +1,6 @@ srcs-y += regulator.c srcs-$(CFG_DT) += regulator_dt.c srcs-$(CFG_REGULATOR_FIXED) += regulator_fixed.c +srcs-$(CFG_REGULATOR_GPIO) += regulator_gpio.c srcs-$(CFG_STM32_VREFBUF) += stm32_vrefbuf.c +srcs-$(CFG_STM32MP13_REGULATOR_IOD) += stm32mp13_regulator_iod.c diff --git a/core/drivers/remoteproc/stm32_remoteproc.c b/core/drivers/remoteproc/stm32_remoteproc.c new file mode 100644 index 0000000000000000000000000000000000000000..e4cd6c8b10ec00eb76530f8cfdd4622f8c6ca986 --- /dev/null +++ b/core/drivers/remoteproc/stm32_remoteproc.c @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include <assert.h> +#include <config.h> +#include <drivers/rstctrl.h> +#include <drivers/stm32_remoteproc.h> +#include <kernel/cache_helpers.h> +#include <kernel/dt_driver.h> +#include <kernel/tee_misc.h> +#include <libfdt.h> +#include <mm/core_memprot.h> +#include <mm/core_mmu.h> + +#define TIMEOUT_US_1MS U(1000) + +/** + * struct stm32_rproc_mem - Memory regions used by the remote processor + * + * @addr: physical base address from the CPU space perspective + * @da: device address corresponding to the physical base address + * from remote processor space perspective + * @size: size of the region + */ +struct stm32_rproc_mem { + paddr_t addr; + paddr_t da; + size_t size; +}; + +/** + * struct stm32_rproc_instance - rproc instance context + * + * @cdata: pointer to the device compatible data + * @link: the node in the rproc_list + * @n_regions: number of memory regions + * @regions: memory regions used + * @mcu_rst: remote processor reset control + * @hold_boot: remote processor hold boot control + */ +struct stm32_rproc_instance { + const struct stm32_rproc_compat_data *cdata; + SLIST_ENTRY(stm32_rproc_instance) link; + size_t n_regions; + struct stm32_rproc_mem *regions; + struct rstctrl *mcu_rst; + struct rstctrl *hold_boot; +}; + +/** + * struct stm32_rproc_compat_data - rproc associated data for compatible list + * + * @rproc_id: identifies the remote processor + */ +struct stm32_rproc_compat_data { + uint32_t rproc_id; +}; + +static SLIST_HEAD(, stm32_rproc_instance) rproc_list = + SLIST_HEAD_INITIALIZER(rproc_list); + +void *stm32_rproc_get(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = NULL; + + SLIST_FOREACH(rproc, &rproc_list, link) + if (rproc->cdata->rproc_id == rproc_id) + break; + + return rproc; +} + +TEE_Result stm32_rproc_start(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + TEE_Result res = TEE_ERROR_GENERIC; + + if (!rproc || !rproc->hold_boot) + return TEE_ERROR_GENERIC; + + /* + * The firmware is started by de-asserting the hold boot and + * asserting it back to avoid auto restart on a crash. + * No need to release the MCU reset as it is automatically released by + * the hardware. + */ + res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS); + if (!res) + res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); + + return res; +} + +static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!rproc->hold_boot || !rproc->mcu_rst) + return TEE_ERROR_GENERIC; + + res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); + if (!res) + res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS); + + return res; +} + +TEE_Result stm32_rproc_stop(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + return rproc_stop(rproc); +} + +TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, + paddr_t *pa) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + unsigned int i = 0; + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) { + /* + * A match between the requested DA memory area and the + * registered regions has been found. + * The PA is the reserved-memory PA address plus the + * delta between the requested DA and the + * reserved-memory DA address. + */ + *pa = mems[i].addr + da - mems[i].da; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, + void **va) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + unsigned int i = 0; + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (!core_is_buffer_inside(pa, size, mems[i].addr, + mems[i].size)) + continue; + *va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size); + if (!*va) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + paddr_t pa = virt_to_phys(va); + unsigned int i = 0; + + if (!rproc || !pa) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (!core_is_buffer_inside(pa, size, mems[i].addr, + mems[i].size)) + continue; + + /* Flush the cache before unmapping the memory */ + dcache_clean_range(va, size); + + if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) { + EMSG("Can't unmap region %#"PRIxPA" size %zu", + pa, size); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_DENIED; +} + +static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region, + const void *fdt, int node) +{ + const fdt32_t *list = NULL; + int ahb_node = 0; + int len = 0; + int nranges = 0; + int i = 0; + + /* + * The match between local and remote processor memory mapping is + * described in the dma-ranges defined by the bus parent node. + */ + ahb_node = fdt_parent_offset(fdt, node); + + list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len); + if (!list) { + if (len != -FDT_ERR_NOTFOUND) + return TEE_ERROR_GENERIC; + /* Same memory mapping */ + DMSG("No dma-ranges found in DT"); + region->da = region->addr; + return TEE_SUCCESS; + } + + if ((len % (sizeof(uint32_t) * 3))) + return TEE_ERROR_GENERIC; + + nranges = len / sizeof(uint32_t); + + for (i = 0; i < nranges; i += 3) { + uint32_t da = fdt32_to_cpu(list[i]); + uint32_t pa = fdt32_to_cpu(list[i + 1]); + uint32_t size = fdt32_to_cpu(list[i + 2]); + + if (core_is_buffer_inside(region->addr, region->size, + pa, size)) { + region->da = da + (region->addr - pa); + return TEE_SUCCESS; + } + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +/* Get device tree memory regions reserved for the Cortex-M and the IPC */ +static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc, + const void *fdt, int node) +{ + const fdt32_t *list = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + struct stm32_rproc_mem *regions = NULL; + int len = 0; + int n_regions = 0; + int i = 0; + + list = fdt_getprop(fdt, node, "memory-region", &len); + if (!list) { + EMSG("No memory regions found in DT"); + return TEE_ERROR_GENERIC; + } + + n_regions = len / sizeof(uint32_t); + + regions = calloc(n_regions, sizeof(*regions)); + if (!regions) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < n_regions; i++) { + int pnode = 0; + + pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i])); + if (pnode < 0) { + res = TEE_ERROR_GENERIC; + goto err; + } + + regions[i].addr = fdt_reg_base_address(fdt, pnode); + regions[i].size = fdt_reg_size(fdt, pnode); + + if (regions[i].addr <= 0 || regions[i].size <= 0) { + res = TEE_ERROR_GENERIC; + goto err; + } + + res = stm32_rproc_get_dma_range(®ions[i], fdt, node); + if (res) + goto err; + + if (!regions[i].addr || !regions[i].size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + DMSG("register region %#"PRIxPA" size %#zx", + regions[i].addr, regions[i].size); + } + + rproc->n_regions = n_regions; + rproc->regions = regions; + + return TEE_SUCCESS; + +err: + free(regions); + + return res; +} + +static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc) +{ + free(rproc->regions); + free(rproc); +} + +static TEE_Result stm32_rproc_probe(const void *fdt, int node, + const void *comp_data) +{ + struct stm32_rproc_instance *rproc = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + rproc = calloc(1, sizeof(*rproc)); + if (!rproc) + return TEE_ERROR_OUT_OF_MEMORY; + + rproc->cdata = comp_data; + + res = stm32_rproc_parse_mems(rproc, fdt, node); + if (res) + goto err; + + res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst); + if (res) + goto err; + + res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot); + if (res) + goto err; + + /* Ensure that the MCU is HOLD */ + if (rproc->mcu_rst) { + res = rproc_stop(rproc); + if (res) + goto err; + } + + /* + * The memory management should be enhance with firewall + * mechanism to map the memory in secure area for the firmware + * loading and then to give exclusive access right to the + * coprocessor (except for the shared memory). + */ + IMSG("Warning: the remoteproc memories are not protected by firewall"); + + SLIST_INSERT_HEAD(&rproc_list, rproc, link); + + return TEE_SUCCESS; + +err: + stm32_rproc_cleanup(rproc); + return res; +} + +static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = { + .rproc_id = STM32_M4_RPROC_ID, +}; + +static const struct dt_device_match stm32_rproc_match_table[] = { + { + .compatible = "st,stm32mp1-m4-tee", + .compat_data = &stm32_rproc_m4_compat, + }, + { } +}; + +DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = { + .name = "stm32-rproc", + .match_table = stm32_rproc_match_table, + .probe = &stm32_rproc_probe, +}; diff --git a/core/drivers/remoteproc/sub.mk b/core/drivers/remoteproc/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..4eb5ca3f29fb4d4ade31e4c828189362eaf20650 --- /dev/null +++ b/core/drivers/remoteproc/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_STM32MP_REMOTEPROC) += stm32_remoteproc.c diff --git a/core/drivers/smccc_trng.c b/core/drivers/smccc_trng.c index 4d28ff0af750e3d8f32e5a494f4a4cc1141471f5..4cb5112d3e2bb254264f5b8b6685ef388535d096 100644 --- a/core/drivers/smccc_trng.c +++ b/core/drivers/smccc_trng.c @@ -184,7 +184,7 @@ static void __maybe_unused smccc_trng_print_info(void) thread_smccc(&args); assert(args.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED); - DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx\n", + DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx", major, minor, (unsigned long)args.a0, (unsigned long)args.a1 >> 16, (unsigned long)args.a1 & GENMASK_32(16, 0), (unsigned long)args.a2 >> 16, diff --git a/core/drivers/sp805_wdt.c b/core/drivers/sp805_wdt.c index 048620cde893e7fc83450e99786bbce2638999a8..cd4624fea97d82e52af1791349b5c684c729caea 100644 --- a/core/drivers/sp805_wdt.c +++ b/core/drivers/sp805_wdt.c @@ -102,19 +102,21 @@ TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, uint32_t itr_num, uint32_t itr_flags, sp805_itr_handler_func_t itr_handler) { - struct itr_handler *wdt_itr; + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_handler *wdt_itr = NULL; assert(!pd->chip.wdt_itr); - wdt_itr = itr_alloc_add(itr_num, wdt_itr_cb, - itr_flags, &pd->chip); - if (!wdt_itr) - return TEE_ERROR_OUT_OF_MEMORY; + res = interrupt_alloc_add_handler(interrupt_get_main_chip(), itr_num, + wdt_itr_cb, itr_flags, + &pd->chip, &wdt_itr); + if (res) + return res; pd->itr_handler = itr_handler; pd->chip.wdt_itr = wdt_itr; - itr_enable(wdt_itr->it); + interrupt_enable(wdt_itr->chip, wdt_itr->it); return TEE_SUCCESS; } diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c index 6450c6fc02dd29df3bb2b8edece4869697f3b176..40f1ccb71768cc206fd6b0f2cedf268dcd563595 100644 --- a/core/drivers/stm32_gpio.c +++ b/core/drivers/stm32_gpio.c @@ -12,6 +12,7 @@ #include <drivers/gpio.h> #include <drivers/pinctrl.h> #include <drivers/stm32_gpio.h> +#include <dt-bindings/gpio/stm32mp_gpio.h> #include <io.h> #include <kernel/dt.h> #include <kernel/boot.h> @@ -32,27 +33,27 @@ #define GPIO_PIN_MAX 15 -#define GPIO_MODER_OFFSET 0x00 -#define GPIO_OTYPER_OFFSET 0x04 -#define GPIO_OSPEEDR_OFFSET 0x08 -#define GPIO_PUPDR_OFFSET 0x0c -#define GPIO_IDR_OFFSET 0x10 -#define GPIO_ODR_OFFSET 0x14 -#define GPIO_BSRR_OFFSET 0x18 -#define GPIO_AFRL_OFFSET 0x20 -#define GPIO_AFRH_OFFSET 0x24 -#define GPIO_SECR_OFFSET 0x30 +#define GPIO_MODER_OFFSET U(0x00) +#define GPIO_OTYPER_OFFSET U(0x04) +#define GPIO_OSPEEDR_OFFSET U(0x08) +#define GPIO_PUPDR_OFFSET U(0x0c) +#define GPIO_IDR_OFFSET U(0x10) +#define GPIO_ODR_OFFSET U(0x14) +#define GPIO_BSRR_OFFSET U(0x18) +#define GPIO_AFRL_OFFSET U(0x20) +#define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) -#define GPIO_ALT_LOWER_LIMIT 0x8 +#define GPIO_ALT_LOWER_LIMIT U(0x8) #define GPIO_MODE_MASK GENMASK_32(1, 0) #define GPIO_OSPEED_MASK GENMASK_32(1, 0) #define GPIO_PUPD_PULL_MASK GENMASK_32(1, 0) #define GPIO_ALTERNATE_MASK GENMASK_32(3, 0) -#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_SHIFT U(12) #define DT_GPIO_BANK_MASK GENMASK_32(16, 12) -#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_SHIFT U(8) #define DT_GPIO_PIN_MASK GENMASK_32(11, 8) #define DT_GPIO_MODE_MASK GENMASK_32(7, 0) @@ -131,7 +132,6 @@ struct stm32_pinctrl_array { * @bank_id: Id of the bank. * @lock: lock protecting the GPIO bank access. * @sec_support: True if bank supports pin security protection, otherwise false - * @seccfgr: Secure configuration register value. * @link: Link in bank list */ struct stm32_gpio_bank { @@ -141,15 +141,19 @@ struct stm32_gpio_bank { unsigned int ngpios; unsigned int bank_id; unsigned int lock; + bool sec_support; STAILQ_ENTRY(stm32_gpio_bank) link; }; -/* +/** * Compatibility information of supported banks - * @gpioz True if bank is a GPIOZ bank + * + * @gpioz: True if bank is a GPIOZ bank + * @secure_control: Identify GPIO security bank capability. */ struct bank_compat { bool gpioz; + bool secure_control; }; static unsigned int gpio_lock; @@ -645,10 +649,15 @@ static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node, panic("missing reg size property"); DMSG("Bank name %s", fdt_get_name(fdt, node, NULL)); - bank->base = io_pa_or_va_secure(&pa_va, blen); bank->bank_id = dt_get_bank_id(fdt, node); bank->clock = clk; bank->gpio_chip.ops = &stm32_gpio_ops; + bank->sec_support = compat->secure_control; + if (bank->sec_support) + bank->base = io_pa_or_va_secure(&pa_va, blen); + else + bank->base = io_pa_or_va_nsec(&pa_va, blen); + assert(bank->base); /* Parse gpio-ranges with its 4 parameters */ cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); @@ -675,11 +684,11 @@ static void set_bank_gpio_non_secure(struct stm32_gpio_bank *bank) { unsigned int pin = 0; - for (pin = 0; pin <= bank->ngpios; pin++) + for (pin = 0; pin < bank->ngpios; pin++) stm32_gpio_set_secure_cfg(bank->bank_id, pin, false); } -/* Parse a pinctrl node to register the GPIO banks it describes */ +/* Parse a pinctrl node to register and configure the GPIO banks it describes */ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, const void *compat_data) { @@ -725,8 +734,30 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, STAILQ_INSERT_TAIL(&bank_list, bank, link); - if (IS_ENABLED(CFG_STM32MP13)) - set_bank_gpio_non_secure(bank); + DMSG("Registered GPIO bank %c (%d pins) @%#"PRIxVA, + bank->bank_id + 'A', bank->ngpios, bank->base); + + assert(bank->ngpios <= GPIO_PIN_MAX + 1); + + if (bank->sec_support) { + uint32_t seccfgr = 0; + unsigned int i = 0; + int lenp = 0; + + cuint = fdt_getprop(fdt, b_node, "st,protreg", + &lenp); + if (!cuint) { + set_bank_gpio_non_secure(bank); + continue; + } + + seccfgr = fdt32_to_cpu(*cuint); + for (i = 0; i < bank->ngpios; i++) + stm32_gpio_set_secure_cfg(bank->bank_id, + i, + seccfgr & + TZPROT(i)); + } } else { if (len != -FDT_ERR_NOTFOUND) panic(); @@ -736,33 +767,6 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, return TEE_SUCCESS; } - -int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank) -{ - int node = 0; - const fdt32_t *cuint = NULL; - - fdt_for_each_subnode(node, fdt, pinctrl_node) { - if (!fdt_getprop(fdt, node, "gpio-controller", NULL)) - continue; - - cuint = fdt_getprop(fdt, node, "reg", NULL); - if (!cuint) - continue; - - if (fdt32_to_cpu(*cuint) != stm32_get_gpio_bank_offset(bank)) - continue; - - cuint = fdt_getprop(fdt, node, "ngpios", NULL); - if (!cuint) - panic(); - - return (int)fdt32_to_cpu(*cuint); - } - - return -1; -} - void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, bool secure) { @@ -778,6 +782,8 @@ void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, else io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); + FMSG("Set secure GPIO: bank %c pin %u", bank->bank_id + 'A', pin); + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); clk_disable(bank->clock); } @@ -950,16 +956,22 @@ static TEE_Result stm32_pinctrl_probe(const void *fdt, int node, static const struct dt_device_match stm32_pinctrl_match_table[] = { { .compatible = "st,stm32mp135-pinctrl", - .compat_data = &(struct bank_compat){ }, - + .compat_data = &(struct bank_compat){ + .secure_control = true, + }, }, { .compatible = "st,stm32mp157-pinctrl", - .compat_data = &(struct bank_compat){ }, + .compat_data = &(struct bank_compat){ + .secure_control = false, + }, }, { .compatible = "st,stm32mp157-z-pinctrl", - .compat_data = &(struct bank_compat){ .gpioz = true, }, + .compat_data = &(struct bank_compat){ + .gpioz = true, + .secure_control = true, + }, }, { } }; diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c index fd2899f9a02cb35ad213b1a153f5cb6834a28739..c7b7ae86bc43433e5f1b92a556cee88e117b2cc9 100644 --- a/core/drivers/stm32_iwdg.c +++ b/core/drivers/stm32_iwdg.c @@ -73,7 +73,7 @@ /* * IWDG watch instance data * @base - IWDG interface IOMEM base address - * @clock - Bus clock + * @clk_pclk - Bus clock * @clk_lsi - IWDG source clock * @flags - Property flags for the IWDG instance * @timeout - Watchdog elaspure timeout @@ -82,7 +82,7 @@ */ struct stm32_iwdg_device { struct io_pa_va base; - struct clk *clock; + struct clk *clk_pclk; struct clk *clk_lsi; uint32_t flags; unsigned long timeout; @@ -90,8 +90,6 @@ struct stm32_iwdg_device { SLIST_ENTRY(stm32_iwdg_device) link; }; -static unsigned int iwdg_lock = SPINLOCK_UNLOCK; - static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list = SLIST_HEAD_INITIALIZER(iwdg_dev_list_head); @@ -105,7 +103,12 @@ static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg) return iwdg->flags & IWDG_FLAGS_NON_SECURE; } -static bool is_enable(struct stm32_iwdg_device *iwdg) +static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg) +{ + iwdg->flags |= IWDG_FLAGS_ENABLED; +} + +static bool iwdg_wdt_is_enabled(struct stm32_iwdg_device *iwdg) { return iwdg->flags & IWDG_FLAGS_ENABLED; } @@ -134,7 +137,7 @@ static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg) if (timeout_elapsed(timeout_ref)) break; - if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)) + if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) return TEE_ERROR_GENERIC; return TEE_SUCCESS; @@ -146,14 +149,12 @@ static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg) vaddr_t iwdg_base = get_base(iwdg); uint32_t rlr_value = 0; - assert(is_enable(iwdg)); + assert(iwdg_wdt_is_enabled(iwdg)); rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout); if (!rlr_value) return TEE_ERROR_GENERIC; - clk_enable(iwdg->clock); - io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value); @@ -161,25 +162,19 @@ static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg) res = iwdg_wait_sync(iwdg); - clk_disable(iwdg->clock); - return res; } static void iwdg_start(struct stm32_iwdg_device *iwdg) { - clk_enable(iwdg->clock); io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY); - clk_disable(iwdg->clock); - iwdg->flags |= IWDG_FLAGS_ENABLED; + iwdg_wdt_set_enabled(iwdg); } static void iwdg_refresh(struct stm32_iwdg_device *iwdg) { - clk_enable(iwdg->clock); io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); - clk_disable(iwdg->clock); } /* Operators for watchdog OP-TEE interface */ @@ -188,6 +183,23 @@ static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip) return container_of(chip, struct stm32_iwdg_device, wdt_chip); } +static TEE_Result iwdg_wdt_init(struct wdt_chip *chip, + unsigned long *min_timeout, + unsigned long *max_timeout) +{ + struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); + unsigned long rate = clk_get_rate(iwdg->clk_lsi); + + if (!rate) + return TEE_ERROR_GENERIC; + + /* Be safe and expect any counter to be above 2 */ + *min_timeout = 3 * IWDG_PRESCALER_256 / rate; + *max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate; + + return TEE_SUCCESS; +} + static void iwdg_wdt_start(struct wdt_chip *chip) { struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); @@ -215,7 +227,7 @@ static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip, iwdg->timeout = timeout; - if (is_enable(iwdg)) { + if (iwdg_wdt_is_enabled(iwdg)) { TEE_Result res = TEE_ERROR_GENERIC; res = configure_timeout(iwdg); @@ -227,24 +239,13 @@ static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip, } static const struct wdt_ops stm32_iwdg_ops = { + .init = iwdg_wdt_init, .start = iwdg_wdt_start, .ping = iwdg_wdt_refresh, .set_timeout = iwdg_wdt_set_timeout, }; DECLARE_KEEP_PAGER(stm32_iwdg_ops); -/* Refresh all registered watchdogs */ -void stm32_iwdg_refresh(void) -{ - struct stm32_iwdg_device *iwdg = NULL; - uint32_t exceptions = cpu_spin_lock_xsave(&iwdg_lock); - - SLIST_FOREACH(iwdg, &iwdg_dev_list, link) - iwdg_refresh(iwdg); - - cpu_spin_unlock_xrestore(&iwdg_lock, exceptions); -} - /* Driver initialization */ static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg, const void *fdt, int node) @@ -259,7 +260,7 @@ static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg, dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) panic(); - res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clock); + res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clk_pclk); if (res) return res; @@ -336,8 +337,9 @@ static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg, if (otp_data.disable_on_standby) iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; - /* Enable watchdog source clock once for all */ + /* Enable watchdog source and bus clocks once for all */ clk_enable(iwdg->clk_lsi); + clk_enable(iwdg->clk_pclk); if (otp_data.hw_enabled) { iwdg->flags |= IWDG_FLAGS_ENABLED; diff --git a/core/drivers/stm32_rng.c b/core/drivers/stm32_rng.c index ef0f36278714e6faafa3ced59ae649f349225381..af234fa9a589ce5c64b9296499ae582a514e78a7 100644 --- a/core/drivers/stm32_rng.c +++ b/core/drivers/stm32_rng.c @@ -279,9 +279,15 @@ static TEE_Result init_rng(void) io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV, clock_div << RNG_CR_CLKDIV_SHIFT); - /* No need to wait for RNG_CR_CONDRST toggle as we enable clk */ io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); + + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) + if (timeout_elapsed(timeout_ref)) + break; + if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) + panic(); } else { io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask); } @@ -312,7 +318,10 @@ static TEE_Result stm32_rng_read(uint8_t *out, size_t size) return TEE_ERROR_NOT_SUPPORTED; } - clk_enable(stm32_rng->clock); + rc = clk_enable(stm32_rng->clock); + if (rc) + return rc; + rng_base = get_base(); /* Arm timeout */ @@ -388,14 +397,24 @@ static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr) io_write32(base + RNG_SR, 0); if (stm32_rng->ddata->has_cond_reset) { + uint64_t timeout_ref = 0; + /* - * Correct configuration in bits [29:4] must be set in the same - * access that set RNG_CR_CONDRST bit. Else config setting is - * not taken into account. + * Configuration must be set in the same access that sets + * RNG_CR_CONDRST bit. Otherwise, the configuration setting is + * not taken into account. CONFIGLOCK bit is always cleared in + * this configuration. */ io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST); io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); + + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + while (io_read32(base + RNG_CR) & RNG_CR_CONDRST) + if (timeout_elapsed(timeout_ref)) + break; + if (io_read32(base + RNG_CR) & RNG_CR_CONDRST) + panic(); } else { io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr); } @@ -460,7 +479,7 @@ static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node) } static TEE_Result stm32_rng_probe(const void *fdt, int offs, - const void *compat_data __unused) + const void *compat_data) { TEE_Result res = TEE_ERROR_GENERIC; diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c index 3862b607cc13ccd1cacecffe857b6c93a4da69d2..f7375256fe20d201a92840b63d7ff6f294705e8e 100644 --- a/core/drivers/stm32_uart.c +++ b/core/drivers/stm32_uart.c @@ -8,6 +8,7 @@ #include <drivers/clk.h> #include <drivers/clk_dt.h> #include <drivers/serial.h> +#include <drivers/stm32_gpio.h> #include <drivers/stm32_uart.h> #include <io.h> #include <keep.h> @@ -38,12 +39,12 @@ * Bit 5 RXNE: Read data register not empty/RXFIFO not empty * Bit 6 TC: Transmission complete * Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full - * Bit 27 TXFE: TXFIFO threshold reached + * Bit 23 TXFE: TXFIFO empty */ #define USART_ISR_RXNE_RXFNE BIT(5) #define USART_ISR_TC BIT(6) #define USART_ISR_TXE_TXFNF BIT(7) -#define USART_ISR_TXFE BIT(27) +#define USART_ISR_TXFE BIT(23) static vaddr_t loc_chip_to_base(struct serial_chip *chip) { @@ -110,22 +111,31 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base) static void register_secure_uart(struct stm32_uart_pdata *pd) { - size_t __maybe_unused n = 0; - +#ifndef CFG_STM32MP25 stm32mp_register_secure_periph_iomem(pd->base.pa); stm32mp_register_secure_pinctrl(pd->pinctrl); if (pd->pinctrl_sleep) stm32mp_register_secure_pinctrl(pd->pinctrl_sleep); +#else + stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); + if (pd->pinctrl_sleep) + stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); +#endif } static void register_non_secure_uart(struct stm32_uart_pdata *pd) { - size_t __maybe_unused n = 0; - +#ifndef CFG_STM32MP25 stm32mp_register_non_secure_periph_iomem(pd->base.pa); stm32mp_register_non_secure_pinctrl(pd->pinctrl); if (pd->pinctrl_sleep) stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep); +#else + stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); + if (pd->pinctrl_sleep) + stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); +#endif + } struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk index 9e7625ae50d8661f9feeada43b8feda75bc04465..0bd5bc242290dee0ad3193b622a38e7def399a3c 100644 --- a/core/drivers/sub.mk +++ b/core/drivers/sub.mk @@ -77,14 +77,17 @@ srcs-$(CFG_VERSAL_PUF) += versal_puf.c srcs-$(CFG_VERSAL_HUK) += versal_huk.c srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c srcs-$(CFG_RISCV_PLIC) += plic.c +srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c subdirs-y += crypto subdirs-$(CFG_BNXT_FW) += bnxt subdirs-$(CFG_DRIVERS_CLK) += clk subdirs-$(CFG_DRIVERS_GPIO) += gpio subdirs-$(CFG_DRIVERS_I2C) += i2c +subdirs-$(CFG_DRIVERS_NVMEM) += nvmem subdirs-$(CFG_DRIVERS_PINCTRL) += pinctrl subdirs-$(CFG_DRIVERS_REGULATOR) += regulator subdirs-$(CFG_DRIVERS_RSTCTRL) += rstctrl +subdirs-$(CFG_DRIVERS_REMOTEPROC) += remoteproc subdirs-$(CFG_SCMI_MSG_DRIVERS) += scmi-msg subdirs-y += imx subdirs-y += pm diff --git a/core/drivers/xiphera_trng.c b/core/drivers/xiphera_trng.c index 9786c19a474f18c7fd75ceb60bf22d500293d9e9..970acf527df4ed17d25c08b47a7d3e6491ab8885 100644 --- a/core/drivers/xiphera_trng.c +++ b/core/drivers/xiphera_trng.c @@ -134,7 +134,7 @@ static TEE_Result xiphera_trng_probe(const void *fdt, int node, udelay(200); status = io_read32(xiphera_trng_base + STATUS_REG); if (status != TRNG_ACK_RESET) { - EMSG("Failed to reset TRNG\n"); + EMSG("Failed to reset TRNG"); return TEE_ERROR_GENERIC; } } @@ -159,17 +159,17 @@ static TEE_Result xiphera_trng_probe(const void *fdt, int node, * in debugging TRNG implementation in FPGA */ if (status == TRNG_FAILED_STARTUP) { - EMSG("Startup tests have failed\n"); + EMSG("Startup tests have failed"); return TEE_ERROR_GENERIC; } - EMSG("Startup tests yielded no response -> TRNG stuck\n"); + EMSG("Startup tests yielded no response -> TRNG stuck"); return TEE_ERROR_GENERIC; } io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); - DMSG("TRNG initialized\n"); + DMSG("TRNG initialized"); return TEE_SUCCESS; } diff --git a/core/include/bench.h b/core/include/bench.h index cdff5773418ec12a3a126e7ef4a975c02ca89527..d9f3cdd3f2285f74baa7a512bbe471325baee6cb 100644 --- a/core/include/bench.h +++ b/core/include/bench.h @@ -3,8 +3,8 @@ * Copyright (c) 2017, Linaro Limited */ -#ifndef BENCH_H -#define BENCH_H +#ifndef __BENCH_H +#define __BENCH_H #include <inttypes.h> #include <mm/core_memprot.h> @@ -57,4 +57,4 @@ void bm_timestamp(void); static inline void bm_timestamp(void) {} #endif /* CFG_TEE_BENCHMARK */ -#endif /* BENCH_H */ +#endif /* __BENCH_H */ diff --git a/core/include/console.h b/core/include/console.h index f2e57fb7d0a02f8d4b628d00eb0a2b08e56132b4..f9cfaca5133fcd48bfee530be33b1c2fa833e925 100644 --- a/core/include/console.h +++ b/core/include/console.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef CONSOLE_H -#define CONSOLE_H +#ifndef __CONSOLE_H +#define __CONSOLE_H #include <compiler.h> #include <tee_api_types.h> @@ -51,5 +51,5 @@ static inline void configure_console_from_dt(void) {} #endif /* !CFG_DT */ -#endif /* CONSOLE_H */ +#endif /* __CONSOLE_H */ diff --git a/core/include/crypto/crypto_se.h b/core/include/crypto/crypto_se.h index eb7452faa2ef5ead7589a31825a2d2b2c00f749b..d8471e51a5be518bf5e249764e179f8a137a7a6b 100644 --- a/core/include/crypto/crypto_se.h +++ b/core/include/crypto/crypto_se.h @@ -10,8 +10,8 @@ * These requests shall be handled in the secure element normally placed on * a serial communication bus (SPI, I2C). */ -#ifndef __CRYPTO_SE_H -#define __CRYPTO_SE_H +#ifndef __CRYPTO_CRYPTO_SE_H +#define __CRYPTO_CRYPTO_SE_H #include <tee_api_types.h> diff --git a/core/include/crypto/sm2-kdf.h b/core/include/crypto/sm2-kdf.h index 5a012c0d959628fa786f44bf2fa10197afe044e5..4ac246bbc882fb63eac4620e6c56f13d920cda03 100644 --- a/core/include/crypto/sm2-kdf.h +++ b/core/include/crypto/sm2-kdf.h @@ -3,11 +3,11 @@ * Copyright (c) 2020-2021, Huawei Technologies Co., Ltd */ -#ifndef CRYPTO_SM2_KDF_H -#define CRYPTO_SM2_KDF_H +#ifndef __CRYPTO_SM2_KDF_H +#define __CRYPTO_SM2_KDF_H #include <stdint.h> #include <tee_api_types.h> TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen); -#endif /* CRYPTO_SM2_KDF_H */ +#endif /* __CRYPTO_SM2_KDF_H */ diff --git a/core/include/drivers/amlogic_uart.h b/core/include/drivers/amlogic_uart.h index 97b55f226b0cda0de36fde5b19474b166d81fb3b..e575afeabf036ffd45e7e7ad3e4376bc7a93e844 100644 --- a/core/include/drivers/amlogic_uart.h +++ b/core/include/drivers/amlogic_uart.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ -#ifndef AMLOGIC_UART_H -#define AMLOGIC_UART_H +#ifndef __DRIVERS_AMLOGIC_UART_H +#define __DRIVERS_AMLOGIC_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -13,4 +13,4 @@ struct amlogic_uart_data { void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base); -#endif /* AMLOGIC_UART_H */ +#endif /* __DRIVERS_AMLOGIC_UART_H */ diff --git a/core/include/drivers/atmel_uart.h b/core/include/drivers/atmel_uart.h index aa5563f709d173e69211ebe7757e059680873164..2639fce72499e43305bfe19f879ba44d254122d3 100644 --- a/core/include/drivers/atmel_uart.h +++ b/core/include/drivers/atmel_uart.h @@ -25,8 +25,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ATMEL_UART_H -#define ATMEL_UART_H +#ifndef __DRIVERS_ATMEL_UART_H +#define __DRIVERS_ATMEL_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -38,4 +38,4 @@ struct atmel_uart_data { void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base); -#endif /* ATMEL_UART_H */ +#endif /* __DRIVERS_ATMEL_UART_H */ diff --git a/core/include/drivers/bcm/bnxt.h b/core/include/drivers/bcm/bnxt.h index 7136c7efa99b139b8a4c0e305665bf9a5b4e177a..51aae18d9ce93bfc0a56de043f2d25cbb6a32548 100644 --- a/core/include/drivers/bcm/bnxt.h +++ b/core/include/drivers/bcm/bnxt.h @@ -3,8 +3,8 @@ * Copyright 2019 Broadcom. */ -#ifndef BNXT_H -#define BNXT_H +#ifndef __DRIVERS_BCM_BNXT_H +#define __DRIVERS_BCM_BNXT_H #include <compiler.h> #include <io.h> diff --git a/core/include/drivers/bcm_gpio.h b/core/include/drivers/bcm_gpio.h index 6606656bf76a1ed9c1dab8f71c64fad729102c13..7d5e408af0a566444060f8f4c5f38bb343465cc6 100644 --- a/core/include/drivers/bcm_gpio.h +++ b/core/include/drivers/bcm_gpio.h @@ -3,8 +3,8 @@ * Copyright 2019 Broadcom. */ -#ifndef BCM_GPIO_H -#define BCM_GPIO_H +#ifndef __DRIVERS_BCM_GPIO_H +#define __DRIVERS_BCM_GPIO_H #include <drivers/gpio.h> #include <stdlib.h> @@ -30,4 +30,4 @@ struct bcm_gpio_chip { struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin); /* Set gpiopin as secure */ void iproc_gpio_set_secure(int gpiopin); -#endif /* BCM_GPIO_H */ +#endif /* __DRIVERS_BCM_GPIO_H */ diff --git a/core/include/drivers/bcm_hwrng.h b/core/include/drivers/bcm_hwrng.h index abf213df6d396d844211274ef0941f39900c6649..b4d84f967d4d672b04f5a7d7a397dbc67a8eff29 100644 --- a/core/include/drivers/bcm_hwrng.h +++ b/core/include/drivers/bcm_hwrng.h @@ -3,11 +3,11 @@ * Copyright 2019 Broadcom. */ -#ifndef BCM_HWRNG_H -#define BCM_HWRNG_H +#ifndef __DRIVERS_BCM_HWRNG_H +#define __DRIVERS_BCM_HWRNG_H #include <stdlib.h> uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read); -#endif /* BCM_HWRNG_H */ +#endif /* __DRIVERS_BCM_HWRNG_H */ diff --git a/core/include/drivers/bcm_sotp.h b/core/include/drivers/bcm_sotp.h index 2476004251484e53ca1718dccb26026a6dd747a2..aa13270434a1171e22464d9cde4fa291eef6339d 100644 --- a/core/include/drivers/bcm_sotp.h +++ b/core/include/drivers/bcm_sotp.h @@ -3,8 +3,8 @@ * Copyright 2019 Broadcom. */ -#ifndef BCM_SOTP_H -#define BCM_SOTP_H +#ifndef __DRIVERS_BCM_SOTP_H +#define __DRIVERS_BCM_SOTP_H #include <stdint.h> #include <tee_api.h> diff --git a/core/include/drivers/caam_extension.h b/core/include/drivers/caam_extension.h index d0232176ee15885631694e1ba8427fed8ec5812f..41ccec05605ba042bcb9391b9a8480b44d4e4fb7 100644 --- a/core/include/drivers/caam_extension.h +++ b/core/include/drivers/caam_extension.h @@ -52,4 +52,4 @@ TEE_Result caam_mp_sign(uint8_t *data, size_t *data_size, uint8_t *sig, TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size, uint8_t *dek, size_t dek_size); #endif /* CFG_NXP_CAAM_DEK_DRV */ -#endif /* __CAAM_EXTENSION_H__ */ +#endif /* __DRIVERS_CAAM_EXTENSION_H__ */ diff --git a/core/include/drivers/cbmem_console.h b/core/include/drivers/cbmem_console.h index c8234d3b6f1080bd394986d5a164a5323c18b20c..a8b695a932d8d56c28bd4610afe0d11df59a2b08 100644 --- a/core/include/drivers/cbmem_console.h +++ b/core/include/drivers/cbmem_console.h @@ -2,12 +2,12 @@ /* * Copyright (c) 2023, Google Limited */ -#ifndef DRIVERS_CBMEM_CONSOLE_H -#define DRIVERS_CBMEM_CONSOLE_H +#ifndef __DRIVERS_CBMEM_CONSOLE_H +#define __DRIVERS_CBMEM_CONSOLE_H #include <stdbool.h> bool cbmem_console_init_from_dt(void *fdt); -#endif /* DRIVERS_CBMEM_CONSOLE_H */ +#endif /* __DRIVERS_CBMEM_CONSOLE_H */ diff --git a/core/include/drivers/cdns_uart.h b/core/include/drivers/cdns_uart.h index 19516ff8681b8681e2656137856b1876638147e8..b5ee11234e60ec97bca28d43bd9ae809e1f5f7ed 100644 --- a/core/include/drivers/cdns_uart.h +++ b/core/include/drivers/cdns_uart.h @@ -26,8 +26,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CDNS_UART_H -#define CDNS_UART_H +#ifndef __DRIVERS_CDNS_UART_H +#define __DRIVERS_CDNS_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -40,4 +40,4 @@ struct cdns_uart_data { void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); -#endif /* CDNS_UART_H */ +#endif /* __DRIVERS_CDNS_UART_H */ diff --git a/core/include/drivers/clk.h b/core/include/drivers/clk.h index 13cc9faee679b1dbf739626c1d285efc1292d67a..20b7d54052a0d29a249fe99e10544266dc2b5b17 100644 --- a/core/include/drivers/clk.h +++ b/core/include/drivers/clk.h @@ -8,6 +8,7 @@ #include <kernel/refcount.h> #include <stdint.h> +#include <sys/queue.h> #include <tee_api_types.h> /* Flags for clock */ @@ -26,6 +27,7 @@ * @enabled_count: Enable/disable reference counter * @num_parents: Number of parents * @parents: Array of possible parents of the clock + * @link: Link the clock list */ struct clk { const char *name; @@ -35,6 +37,9 @@ struct clk { unsigned long rate; unsigned int flags; struct refcount enabled_count; +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + SLIST_ENTRY(clk) link; +#endif size_t num_parents; struct clk *parents[]; }; @@ -194,4 +199,12 @@ TEE_Result clk_set_parent(struct clk *clk, struct clk *parent); TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, unsigned long *rates, size_t *nb_elts); +/* Print current clock tree summary to output console with debug trace level */ +#ifdef CFG_DRIVERS_CLK +void clk_print_tree(void); +#else +static inline void clk_print_tree(void) +{ +} +#endif /* CFG_DRIVERS_CLK */ #endif /* __DRIVERS_CLK_H */ diff --git a/core/include/drivers/clk_dt.h b/core/include/drivers/clk_dt.h index eb164acb8934b627df5f61d9ceef371273ff445d..5ea10ade83395dc88a474f9f9ebcb976c3aba512 100644 --- a/core/include/drivers/clk_dt.h +++ b/core/include/drivers/clk_dt.h @@ -6,6 +6,7 @@ #ifndef __DRIVERS_CLK_DT_H #define __DRIVERS_CLK_DT_H +#include <drivers/clk.h> #include <kernel/dt_driver.h> #include <scattered_array.h> #include <stdint.h> diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h index cb580ec1cfd1c6fe5c6401704a7f2a700642b12c..498e3c8a78a87f8b9fd11224b4d93e5c1a762330 100644 --- a/core/include/drivers/gic.h +++ b/core/include/drivers/gic.h @@ -25,15 +25,34 @@ #define GIC_SPI_TO_ITNUM(x) ((x) + GIC_SPI_BASE) /* - * The two gic_init_* functions initializes the struct gic_data which is - * then used by the other functions. + * Default lowest ID for secure SGIs, note that this does not account for + * interrupts donated to non-secure world with gic_init_donate_sgi_to_ns(). */ +#define GIC_SGI_SEC_BASE 8 +/* Max ID for secure SGIs */ +#define GIC_SGI_SEC_MAX 15 -/* Initialize GIC */ -void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa); +/* + * The two gic_init() and gic_init_v3() functions initializes the struct + * gic_data which is then used by the other functions. These two functions + * also initializes the GIC and are only supposed to be called from the + * primary boot CPU. + */ +void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa); +static inline void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) +{ + gic_init_v3(gicc_base_pa, gicd_base_pa, 0); +} + +/* Donates one of the secure SGIs to normal world */ +void gic_init_donate_sgi_to_ns(size_t it); -/* Only initialize CPU GIC interface, mainly use for secondary CPUs */ -void gic_cpu_init(void); +/* + * Does per-CPU specific GIC initialization, should be called by all + * secondary CPUs when booting. + */ +void gic_init_per_cpu(void); /* Print GIC state to console */ void gic_dump_state(void); diff --git a/core/include/drivers/gpio.h b/core/include/drivers/gpio.h index 7ce00e1f93f2d54462e2693e1c2288a525669acd..b6406d45e9ce317efb619446b201aad461d295a4 100644 --- a/core/include/drivers/gpio.h +++ b/core/include/drivers/gpio.h @@ -3,8 +3,8 @@ * Copyright (c) 2016, Linaro Limited */ -#ifndef DRIVERS_GPIO_H -#define DRIVERS_GPIO_H +#ifndef __DRIVERS_GPIO_H +#define __DRIVERS_GPIO_H #include <assert.h> #include <dt-bindings/gpio/gpio.h> @@ -219,4 +219,4 @@ static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, data, DT_DRIVER_GPIO); } -#endif /* DRIVERS_GPIO_H */ +#endif /* __DRIVERS_GPIO_H */ diff --git a/core/include/drivers/hi16xx_uart.h b/core/include/drivers/hi16xx_uart.h index 83413fc0e20e0a6baba2f4d4eb7c6c2caf12d700..9fb11a4f5d35b461373491f19a745298e605a3f2 100644 --- a/core/include/drivers/hi16xx_uart.h +++ b/core/include/drivers/hi16xx_uart.h @@ -7,8 +7,8 @@ * UART driver for Hisilicon Hi16xx and Phosphor V660 (hip05) SoCs */ -#ifndef HI16XX_UART_H -#define HI16XX_UART_H +#ifndef __DRIVERS_HI16XX_UART_H +#define __DRIVERS_HI16XX_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -23,4 +23,4 @@ struct hi16xx_uart_data { void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); -#endif /* HI16XX_UART_H */ +#endif /* __DRIVERS_HI16XX_UART_H */ diff --git a/core/include/drivers/imx/dcp.h b/core/include/drivers/imx/dcp.h index a01ae3011e4bd8c910859e8596909d48152df42a..28ff0803101bfe6fb72c7e7d59593079e680543d 100644 --- a/core/include/drivers/imx/dcp.h +++ b/core/include/drivers/imx/dcp.h @@ -2,8 +2,8 @@ /* * Copyright 2020 NXP */ -#ifndef __IMX_DCP_H__ -#define __IMX_DCP_H__ +#ifndef __DRIVERS_IMX_DCP_H +#define __DRIVERS_IMX_DCP_H #include <compiler.h> #include <tee_api_types.h> @@ -192,4 +192,4 @@ static inline TEE_Result dcp_vbase(vaddr_t *base __unused) } #endif /* CFG_DT */ -#endif /* __IMX_DCP_H__ */ +#endif /* __DRIVERS_IMX_DCP_H */ diff --git a/core/include/drivers/imx_ocotp.h b/core/include/drivers/imx_ocotp.h index 72d4b79609faac6e397a7bee71c803091f31a6f1..d10013515d025f4844d914dce35359f285de12a3 100644 --- a/core/include/drivers/imx_ocotp.h +++ b/core/include/drivers/imx_ocotp.h @@ -3,8 +3,8 @@ * Copyright 2021 NXP */ -#ifndef _IMX_OCOTP_H -#define _IMX_OCOTP_H +#ifndef __DRIVERS_IMX_OCOTP_H +#define __DRIVERS_IMX_OCOTP_H #include <tee_api_types.h> @@ -19,4 +19,4 @@ * @[out]val Shadow register value */ TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val); -#endif /* _IMX_OCOTP_H */ +#endif /* __DRIVERS_IMX_OCOTP_H */ diff --git a/core/include/drivers/imx_uart.h b/core/include/drivers/imx_uart.h index b9df517e5e8ba2da7fafe9f61ca4c56d7c9175d7..a62bd17a26f85d68286fbfafb41a17c69c95cc18 100644 --- a/core/include/drivers/imx_uart.h +++ b/core/include/drivers/imx_uart.h @@ -26,8 +26,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IMX_UART_H -#define IMX_UART_H +#ifndef __DRIVERS_IMX_UART_H +#define __DRIVERS_IMX_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -39,4 +39,4 @@ struct imx_uart_data { void imx_uart_init(struct imx_uart_data *pd, paddr_t base); -#endif /* IMX_UART_H */ +#endif /* __DRIVERS_IMX_UART_H */ diff --git a/core/include/drivers/imx_wdog.h b/core/include/drivers/imx_wdog.h index 2c7607335c068821947a14b0f0a0a203d67e4741..7df879aab4a76953ce95da78d5308d36d8b48eba 100644 --- a/core/include/drivers/imx_wdog.h +++ b/core/include/drivers/imx_wdog.h @@ -25,8 +25,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __IMX_WDOG_H -#define __IMX_WDOG_H +#ifndef __DRIVERS_IMX_WDOG_H +#define __DRIVERS_IMX_WDOG_H #include <compiler.h> diff --git a/core/include/drivers/lpc_uart.h b/core/include/drivers/lpc_uart.h index 3e235b4e2c54909939f2dd5a45ec55b27ceaee97..e219a90b2d5c4e8cc706097100fcf108f6e181e3 100644 --- a/core/include/drivers/lpc_uart.h +++ b/core/include/drivers/lpc_uart.h @@ -3,8 +3,8 @@ * Copyright (c) 2022, HiSilicon Limited */ -#ifndef LPC_UART_H -#define LPC_UART_H +#ifndef __DRIVERS_LPC_UART_H +#define __DRIVERS_LPC_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -50,4 +50,4 @@ struct lpc_uart_data { void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); -#endif /* LPC_UART_H */ +#endif /* __DRIVERS_LPC_UART_H */ diff --git a/core/include/drivers/mvebu_uart.h b/core/include/drivers/mvebu_uart.h index fed9ac8b6192cfba69a194a460820d29f05c8571..a3934287508e797bd80f683ef9edbfc2d5b761bb 100644 --- a/core/include/drivers/mvebu_uart.h +++ b/core/include/drivers/mvebu_uart.h @@ -25,8 +25,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MVEBU_UART_H -#define MVEBU_UART_H +#ifndef __DRIVERS_MVEBU_UART_H +#define __DRIVERS_MVEBU_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -39,4 +39,4 @@ struct mvebu_uart_data { void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate); -#endif /* MVEBU_UART_H */ +#endif /* __DRIVERS_MVEBU_UART_H */ diff --git a/core/include/drivers/ns16550.h b/core/include/drivers/ns16550.h index de0be9eb3704d077535af2e839f91e21c76c14a3..60d3671291f8932260e0a569aab58a821767ff7e 100644 --- a/core/include/drivers/ns16550.h +++ b/core/include/drivers/ns16550.h @@ -26,8 +26,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef NS16550_H -#define NS16550_H +#ifndef __DRIVERS_NS16550_H +#define __DRIVERS_NS16550_H #include <drivers/serial.h> #include <io.h> @@ -64,4 +64,4 @@ static inline void serial_out(vaddr_t addr, uint8_t io_width, int ch) void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width, uint8_t reg_shift); -#endif /* NS16550_H */ +#endif /* __DRIVERS_NS16550_H */ diff --git a/core/include/drivers/nvmem.h b/core/include/drivers/nvmem.h new file mode 100644 index 0000000000000000000000000000000000000000..5db573d1f0c492e3575a80a3d75cb302360bb244 --- /dev/null +++ b/core/include/drivers/nvmem.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Microchip + */ + +#ifndef __DRIVERS_NVMEM_H +#define __DRIVERS_NVMEM_H + +#include <kernel/dt_driver.h> +#include <tee_api_defines.h> +#include <tee_api_types.h> +#include <types_ext.h> + +struct nvmem_cell; + +/* + * struct nvmem_ops - NVMEM device driver operations + * @read_cell: Allocate @data in the heap and load @len bytes to from an + * NVMEM cell + * @put_cell: Release resources allocated from nvmem_dt_get_func callback + * function + */ +struct nvmem_ops { + /* + * Read data from an NVMEM cell. + * @cell: Cell to read data from + * @data: Output buffer of size greater or equal to @cell->size + */ + TEE_Result (*read_cell)(struct nvmem_cell *cell, uint8_t *data); + void (*put_cell)(struct nvmem_cell *cell); +}; + +/* + * struct nvmem_cell - Description of an NVMEM cell + * @offset: Cell byte offset in the NVMEM device + * @len: Cell byte size + * @ops: NVMEM device driver operation handlers + * @drv_data: NVMEM device driver private data + */ +struct nvmem_cell { + paddr_t offset; + size_t len; + const struct nvmem_ops *ops; + void *drv_data; +}; + +/* + * nvmem_dt_get_func - Typedef of handlers to get an NVMEM cell from a npode + * @args: Reference to phandle arguments + * @data: Pointer to data given at nvmem_dt_get_func() call + * @cell: Output reference to cell instance upon success + * + * Return TEE_SUCCESS in case of success. + * Return TEE_ERROR_DEFER_DRIVER_INIT if NVMEM driver is not initialized + * Return another TEE_Result compliant code otherwise. + */ +typedef TEE_Result (*nvmem_dt_get_func)(struct dt_pargs *args, + void *data, struct nvmem_cell **cell); + +#ifdef CFG_DRIVERS_NVMEM +/** + * nvmem_register_provider() - Register a NVMEM controller + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @get_dt_nvmem: Callback to match the devicetree NVMEM reference with + * nvmem_cell + * @data: Data which will be passed to the get_dt_nvmem callback + * Return a TEE_Result compliant value + */ +static inline TEE_Result nvmem_register_provider(const void *fdt, + int nodeoffset, + nvmem_dt_get_func get_dt_nvmem, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_nvmem, + data, DT_DRIVER_NVMEM); +} + +/** + * nvmem_get_cell_by_name() - Obtain a NVMEM cell from its name in the DT node + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @name: name of the NVMEM cell defined by property nvmem-cell-names to obtain + * from the device tree + * @cell: Pointer filled with the retrieved cell, must be freed after use + using nvmem_put_cell() + * Return a TEE_Result compliant value + */ +TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, + const char *name, struct nvmem_cell **cell); + +/** + * nvmem_get_cell_by_index() - Obtain a NVMEM cell from property nvmem-cells + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @index: Index of the NVMEM cell to obtain from device-tree + * @out_cell: Pointer filled with the retrieved cell, must be freed after use + * using nvmem_put_cell() + * Return a TEE_Result compliant value + */ +TEE_Result nvmem_get_cell_by_index(const void *fdt, + int nodeoffset, + unsigned int index, + struct nvmem_cell **out_cell); + +/** + * nvmem_cell_parse_dt() - Parse device-tree information to fill a NVMEM cell + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the NVMEM cell controller + * @cell: Pointer to cell that will be filled + */ +TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, + struct nvmem_cell *cell); + +/** + * nvmem_put_cell() - Free resource allocated from nvmem_get_cell_by_*() + * + * @cell: Cell to be freed + */ +static inline void nvmem_put_cell(struct nvmem_cell *cell) +{ + if (cell->ops->put_cell) + cell->ops->put_cell(cell); +} + +/* + * nvmem_cell_read() - Read data from a NVMEM cell + * @cell: Cell to read from NVMEM + * @data: Output data read from the cell upon success, byte size >= @cell->size + */ +static inline TEE_Result nvmem_cell_read(struct nvmem_cell *cell, + uint8_t *data) +{ + if (!cell->ops->read_cell) + return TEE_ERROR_NOT_SUPPORTED; + + return cell->ops->read_cell(cell, data); +} + +/* + * nvmem_cell_malloc_and_read() - Allocate and read data from a NVMEM cell + * @cell: Cell to read from NVMEM + * @data: Output allocated buffer where NVMEM cell data are stored upon success + * + * Upon success, the output buffer is allocated with malloc(). Caller is + * responsible for freeing the buffer with free() if needed. + */ +TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, + uint8_t **out_data); + +#else /* CFG_DRIVERS_NVMEM */ +static inline TEE_Result nvmem_register_provider(const void *fdt __unused, + int nodeoffset __unused, + nvmem_dt_get_func fn __unused, + void *data __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result nvmem_get_cell_by_name(const void *fdt __unused, + int nodeoffset __unused, + const char *name __unused, + struct nvmem_cell **c __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline +TEE_Result nvmem_get_cell_by_index(const void *fdt __unused, + int nodeoffset __unused, + unsigned int index __unused, + struct nvmem_cell **cell __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result nvmem_cell_parse_dt(const void *fdt __unused, + int nodeoffset __unused, + struct nvmem_cell *cell __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void nvmem_put_cell(struct nvmem_cell *cell __unused) +{ +} +#endif /* CFG_DRIVERS_NVMEM */ +#endif /* __DRIVERS_NVMEM_H */ diff --git a/core/include/drivers/pl011.h b/core/include/drivers/pl011.h index b46880eebe8dcfdf5fb5f6c0342ad4be96a8151d..59475c1c20b638d24c0591aa0ea86fa12c51954e 100644 --- a/core/include/drivers/pl011.h +++ b/core/include/drivers/pl011.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, Linaro Limited */ -#ifndef PL011_H -#define PL011_H +#ifndef __DRIVERS_PL011_H +#define __DRIVERS_PL011_H #include <types_ext.h> #include <drivers/serial.h> @@ -18,4 +18,4 @@ struct pl011_data { void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate); -#endif /* PL011_H */ +#endif /* __DRIVERS_PL011_H */ diff --git a/core/include/drivers/pl022_spi.h b/core/include/drivers/pl022_spi.h index c20b01be2b28622db627d5258c7defda64929219..0ccef78a20b0c73ab009c2a3aef5fefceca00328 100644 --- a/core/include/drivers/pl022_spi.h +++ b/core/include/drivers/pl022_spi.h @@ -4,8 +4,8 @@ * */ -#ifndef __PL022_SPI_H__ -#define __PL022_SPI_H__ +#ifndef __DRIVERS_PL022_SPI_H +#define __DRIVERS_PL022_SPI_H #include <drivers/gpio.h> #include <spi.h> @@ -42,5 +42,5 @@ struct pl022_data { void pl022_init(struct pl022_data *pd); -#endif /* __PL022_SPI_H__ */ +#endif /* __DRIVERS_PL022_SPI_H */ diff --git a/core/include/drivers/pl061_gpio.h b/core/include/drivers/pl061_gpio.h index 1676b2f22b74fb753f07ad4f3d231cdd86e48251..d6a36c41e2abce7c84a369b2bbcf0e10620ac9e7 100644 --- a/core/include/drivers/pl061_gpio.h +++ b/core/include/drivers/pl061_gpio.h @@ -3,8 +3,8 @@ * Copyright (c) 2016, Linaro Limited */ -#ifndef __PL061_GPIO_H__ -#define __PL061_GPIO_H__ +#ifndef __DRIVERS_PL061_GPIO_H +#define __DRIVERS_PL061_GPIO_H #include <drivers/gpio.h> #include <types_ext.h> @@ -26,4 +26,4 @@ enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin); void pl061_set_mode_control(unsigned int gpio_pin, enum pl061_mode_control hw_sw); -#endif /* __PL061_GPIO_H__ */ +#endif /* __DRIVERS_PL061_GPIO_H */ diff --git a/core/include/drivers/plic.h b/core/include/drivers/plic.h index 148fc1e97a99b95b8839f1b1da83c42f4405e3c4..f1f260430175945c9e429988f5f02fba383435b2 100644 --- a/core/include/drivers/plic.h +++ b/core/include/drivers/plic.h @@ -3,8 +3,8 @@ * Copyright 2022-2023 NXP */ -#ifndef DRIVERS_PLIC_H -#define DRIVERS_PLIC_H +#ifndef __DRIVERS_PLIC_H +#define __DRIVERS_PLIC_H #include <kernel/interrupt.h> #include <kernel/misc.h> @@ -15,4 +15,4 @@ void plic_hart_init(void); void plic_it_handle(void); void plic_dump_state(void); -#endif /*DRIVERS_PLIC_H*/ +#endif /*__DRIVERS_PLIC_H*/ diff --git a/core/include/drivers/regulator.h b/core/include/drivers/regulator.h index e7c52a7b3eddbf95da2b1eb011cb8008f6161501..c9266bf323c6dfce501b6f8a0e8691199068b3b4 100644 --- a/core/include/drivers/regulator.h +++ b/core/include/drivers/regulator.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2023, STMicroelectronics */ -#ifndef DRIVERS_REGULATOR_H -#define DRIVERS_REGULATOR_H +#ifndef __DRIVERS_REGULATOR_H +#define __DRIVERS_REGULATOR_H #include <assert.h> #include <bitstring.h> @@ -67,16 +67,14 @@ enum voltage_type { }; /* - * struct regulator_voltages - Voltage levels description + * struct regulator_voltages_desc - Voltage levels description * @type: Type of level description - * @num_levels: Number of cells of @entries when @type is VOLTAGE_TYPE_FULL_LIST - * @entries: Voltage level information in uV + * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST * */ -struct regulator_voltages { +struct regulator_voltages_desc { enum voltage_type type; size_t num_levels; - int entries[]; }; /* @@ -108,7 +106,7 @@ struct regulator { unsigned int refcount; struct mutex lock; /* Concurrent access protection */ struct voltages_fallback { - struct regulator_voltages desc; + struct regulator_voltages_desc desc; int levels[3]; } voltages_fallback; size_t levels_count_fallback; @@ -131,7 +129,8 @@ struct regulator_ops { TEE_Result (*set_voltage)(struct regulator *r, int level_uv); TEE_Result (*get_voltage)(struct regulator *r, int *level_uv); TEE_Result (*supported_voltages)(struct regulator *r, - struct regulator_voltages **voltages); + struct regulator_voltages_desc **desc, + const int **levels); TEE_Result (*supplied_init)(struct regulator *r, const void *fdt, int node); }; @@ -311,8 +310,25 @@ static inline void regulator_get_range(struct regulator *regulator, int *min_uv, /* * regulator_supported_voltages() - Get regulator supported levels in microvolt * @regulator: Regulator reference - * @voltages: Output description supported voltage levels + * @desc: Output reference to supported voltage levels description + * @levels: Output reference to voltage level array, in microvolts + * + * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels + * is defined by @desc->num_levels, each cell being a level in microvolts (uV). + * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells: + * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2] + * is the incremental level step, all in microvolts (uV). */ TEE_Result regulator_supported_voltages(struct regulator *regulator, - struct regulator_voltages **voltages); -#endif /* DRIVERS_REGULATOR_H */ + struct regulator_voltages_desc **desc, + const int **levels); + +/* Print current regulator tree summary to console with debug trace level */ +#ifdef CFG_DRIVERS_REGULATOR +void regulator_print_tree(void); +#else +static inline void regulator_print_tree(void) +{ +} +#endif /* CFG_DRIVERS_REGULATOR */ +#endif /* __DRIVERS_REGULATOR_H */ diff --git a/core/include/drivers/rtc.h b/core/include/drivers/rtc.h index c7f05be598b1314e19e071e933d594bb1866f17f..1e0df82034f3274c36ae5462c6a0f1831c9e7d0f 100644 --- a/core/include/drivers/rtc.h +++ b/core/include/drivers/rtc.h @@ -3,8 +3,8 @@ * Copyright 2022 Microchip. */ -#ifndef DRIVERS_RTC_H -#define DRIVERS_RTC_H +#ifndef __DRIVERS_RTC_H +#define __DRIVERS_RTC_H #include <tee_api_types.h> #include <util.h> @@ -127,4 +127,4 @@ static inline TEE_Result rtc_set_offset(long offset __unused) return TEE_ERROR_NOT_SUPPORTED; } #endif -#endif /* DRIVERS_RTC_H */ +#endif /* __DRIVERS_RTC_H */ diff --git a/core/include/drivers/sam/at91_ddr.h b/core/include/drivers/sam/at91_ddr.h index 84e13e630ac584d5a01dbc33d58278da08a4c65a..5424303ba132e2030f1f426755fa82236dff0ea6 100644 --- a/core/include/drivers/sam/at91_ddr.h +++ b/core/include/drivers/sam/at91_ddr.h @@ -6,8 +6,8 @@ * Nicolas Ferre <nicolas.ferre@atmel.com> */ -#ifndef AT91_DDRSDR_H -#define AT91_DDRSDR_H +#ifndef __DRIVERS_SAM_AT91_DDRSDR_H +#define __DRIVERS_SAM_AT91_DDRSDR_H /* Mode Register */ #define AT91_DDRSDRC_MR 0x00 diff --git a/core/include/drivers/scif.h b/core/include/drivers/scif.h index fe818715943b5d9b2a55b8fff69522a4cf2505dc..7cb3ac015627489f1508d137c581206f2854fea3 100644 --- a/core/include/drivers/scif.h +++ b/core/include/drivers/scif.h @@ -26,8 +26,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SCIF_H -#define SCIF_H +#ifndef __DRIVERS_SCIF_H +#define __DRIVERS_SCIF_H #include <types_ext.h> #include <drivers/serial.h> @@ -41,4 +41,4 @@ struct scif_uart_data { void scif_uart_init(struct scif_uart_data *pd, paddr_t base); -#endif /* SCIF */ +#endif /* __DRIVERS_SCIF_H */ diff --git a/core/include/drivers/scmi-msg.h b/core/include/drivers/scmi-msg.h index 08dd31c674fa74015072bf466d5c16786fa8bd31..c276ea853ce580b0aba64e7273adaab2380cee28 100644 --- a/core/include/drivers/scmi-msg.h +++ b/core/include/drivers/scmi-msg.h @@ -4,8 +4,8 @@ * Copyright (c) 2019-2021, Linaro Limited */ -#ifndef SCMI_MSG_H -#define SCMI_MSG_H +#ifndef __DRIVERS_SCMI_MSG_H +#define __DRIVERS_SCMI_MSG_H #include <compiler.h> #include <kernel/panic.h> @@ -334,7 +334,7 @@ int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, size_t plat_scmi_voltd_count(unsigned int channel_id); /* - * Get clock controller string ID (aka name) + * Get voltage domain string ID (aka name) * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * Return pointer to name or NULL @@ -381,7 +381,7 @@ int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, /* * Set voltage domain level voltage domain * @channel_id: SCMI channel ID - * @scmi_id: SCMI clock ID + * @scmi_id: SCMI voltage domain ID * @level: Target voltage domain level in microvolt * Return a compliant SCMI error code */ @@ -408,4 +408,4 @@ int32_t plat_scmi_voltd_get_config(unsigned int channel_id, int32_t plat_scmi_voltd_set_config(unsigned int channel_id, unsigned int scmi_id, uint32_t config); -#endif /* SCMI_MSG_H */ +#endif /* __DRIVERS_SCMI_MSG_H */ diff --git a/core/include/drivers/scmi.h b/core/include/drivers/scmi.h index 9497206b31985a1e632bc2b35387d352b4787ab9..1e43bac6c5ede15560e9f6af8082e9c15304740b 100644 --- a/core/include/drivers/scmi.h +++ b/core/include/drivers/scmi.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. */ -#ifndef SCMI_MSG_SCMI_H -#define SCMI_MSG_SCMI_H +#ifndef __DRIVERS_SCMI_MSG_SCMI_H +#define __DRIVERS_SCMI_MSG_SCMI_H #define SCMI_PROTOCOL_ID_BASE 0x10 #define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11 @@ -27,4 +27,4 @@ #define SCMI_HARDWARE_ERROR (-9) #define SCMI_PROTOCOL_ERROR (-10) -#endif /* SCMI_MSG_SCMI_H */ +#endif /* __DRIVERS_SCMI_MSG_SCMI_H */ diff --git a/core/include/drivers/serial8250_uart.h b/core/include/drivers/serial8250_uart.h index 40816c9b97e21d66bcdcff4842589485fb47f4da..e56811fb4a7eec6bd886aa0cf24efc49fb3c7e71 100644 --- a/core/include/drivers/serial8250_uart.h +++ b/core/include/drivers/serial8250_uart.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef SERIAL8250_UART_H -#define SERIAL8250_UART_H +#ifndef __DRIVERS_SERIAL8250_UART_H +#define __DRIVERS_SERIAL8250_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -18,5 +18,5 @@ struct serial8250_uart_data { void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); -#endif /* SERIAL8250_UART_H */ +#endif /* __DRIVERS_SERIAL8250_UART_H */ diff --git a/core/include/drivers/sp805_wdt.h b/core/include/drivers/sp805_wdt.h index 0d5d3133bc564e9761eb30597648692d6613486a..a8f8f457366fb262e7d5e46c52495ec39f184a1a 100644 --- a/core/include/drivers/sp805_wdt.h +++ b/core/include/drivers/sp805_wdt.h @@ -3,8 +3,8 @@ * Copyright 2019 Broadcom. */ -#ifndef SP805_WDT_H -#define SP805_WDT_H +#ifndef __DRIVERS_SP805_WDT_H +#define __DRIVERS_SP805_WDT_H #include <drivers/wdt.h> #include <kernel/interrupt.h> @@ -66,4 +66,4 @@ TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, uint32_t itr_num, uint32_t itr_flag, sp805_itr_handler_func_t itr_handler); -#endif /* SP805_WDT_H */ +#endif /* __DRIVERS_SP805_WDT_H */ diff --git a/core/include/drivers/sprd_uart.h b/core/include/drivers/sprd_uart.h index 64826222d6cb08a677990922dfa1c05868c9c0de..8c12c39559b272af33f789a8aa20acb81469b28b 100644 --- a/core/include/drivers/sprd_uart.h +++ b/core/include/drivers/sprd_uart.h @@ -26,8 +26,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SPRD_UART_H -#define SPRD_UART_H +#ifndef __DRIVERS_SPRD_UART_H +#define __DRIVERS_SPRD_UART_H #include <types_ext.h> #include <drivers/serial.h> @@ -39,5 +39,5 @@ struct sprd_uart_data { void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base); -#endif /* SPRD_UART_H */ +#endif /* __DRIVERS_SPRD_UART_H */ diff --git a/core/include/drivers/stih_asc.h b/core/include/drivers/stih_asc.h index 21e829766b503578d2b768bd886d2f01f8430657..79df157b83ccf7bc49428a14c614511f436f46ef 100644 --- a/core/include/drivers/stih_asc.h +++ b/core/include/drivers/stih_asc.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2017, Linaro Limited */ -#ifndef STIH_ASC_H -#define STIH_ASC_H +#ifndef __DRIVERS_STIH_ASC_H +#define __DRIVERS_STIH_ASC_H #include <drivers/serial.h> #include <types_ext.h> @@ -17,5 +17,5 @@ struct stih_asc_pd { void stih_asc_init(struct stih_asc_pd *pb, vaddr_t base); -#endif /* STIH_ASC_H */ +#endif /* __DRIVERS_STIH_ASC_H */ diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h index a5984258230407cafbe8b47ea7d13d1c79e0e899..f0577bc8b104a3ebae2a1dd1337b9d74e5407609 100644 --- a/core/include/drivers/stm32_bsec.h +++ b/core/include/drivers/stm32_bsec.h @@ -3,8 +3,8 @@ * Copyright (c) 2017-2022, STMicroelectronics */ -#ifndef __STM32_BSEC_H -#define __STM32_BSEC_H +#ifndef __DRIVERS_STM32_BSEC_H +#define __DRIVERS_STM32_BSEC_H #include <compiler.h> #include <stdint.h> @@ -199,4 +199,4 @@ TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle, */ TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *sec_state); -#endif /*__STM32_BSEC_H*/ +#endif /*__DRIVERS_STM32_BSEC_H*/ diff --git a/core/include/drivers/stm32_etzpc.h b/core/include/drivers/stm32_etzpc.h index 3a87ff45a1114bada503fdddc25e6db996028c47..48f0385a34747d285bfa4040628785839bb252d0 100644 --- a/core/include/drivers/stm32_etzpc.h +++ b/core/include/drivers/stm32_etzpc.h @@ -4,8 +4,8 @@ * Copyright (c) 2018-2019, STMicroelectronics */ -#ifndef __STM32_ETZPC_H__ -#define __STM32_ETZPC_H__ +#ifndef __DRIVERS_STM32_ETZPC_H +#define __DRIVERS_STM32_ETZPC_H #include <util.h> #include <types_ext.h> @@ -74,4 +74,4 @@ void etzpc_lock_tzma(uint32_t tzma_id); * Return true if TZMA is locked, false otherwise */ bool etzpc_get_lock_tzma(uint32_t tzma_id); -#endif /*__STM32_ETZPC_H__*/ +#endif /*__DRIVERS_STM32_ETZPC_H*/ diff --git a/core/include/drivers/stm32_gpio.h b/core/include/drivers/stm32_gpio.h index adc85358c218516795868804222768c6f0621d07..883888171f3cd58009e4c141c371693453d40170 100644 --- a/core/include/drivers/stm32_gpio.h +++ b/core/include/drivers/stm32_gpio.h @@ -3,8 +3,8 @@ * Copyright (c) 2017-2023, STMicroelectronics */ -#ifndef DRIVERS_STM32_GPIO_H -#define DRIVERS_STM32_GPIO_H +#ifndef __DRIVERS_STM32_GPIO_H +#define __DRIVERS_STM32_GPIO_H #include <assert.h> #include <drivers/pinctrl.h> @@ -26,16 +26,6 @@ struct stm32_pinctrl; void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin, bool secure); -/* - * Get the number of GPIO pins supported by a target GPIO bank - * - * @fdt: device tree reference - * @pinctrl_node: pinctrl node which GPIO bank node belongs to - * @bank: target GPIO bank ID - * Return number of GPIO pins (>= 0) or a negative value on error - */ -int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank); - /* * Configure pin muxing access permission: can be secure or not * @@ -68,4 +58,4 @@ static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused, { } #endif /*CFG_STM32_GPIO*/ -#endif /*DRIVERS_STM32_GPIO_H*/ +#endif /*__DRIVERS_STM32_GPIO_H*/ diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h index a1c83482c98f17d46693ac8bf68fc4ed5fe3e95f..0c955ade2b8b8aa8f3f68f12ac2dfa847820d57c 100644 --- a/core/include/drivers/stm32_i2c.h +++ b/core/include/drivers/stm32_i2c.h @@ -3,8 +3,8 @@ * Copyright (c) 2017-2023, STMicroelectronics */ -#ifndef DRIVERS_STM32_I2C_H -#define DRIVERS_STM32_I2C_H +#ifndef __DRIVERS_STM32_I2C_H +#define __DRIVERS_STM32_I2C_H #include <drivers/clk.h> #include <drivers/i2c.h> @@ -278,4 +278,4 @@ static inline bool i2c_is_secure(struct i2c_handle_s *hi2c) return hi2c->dt_status == DT_STATUS_OK_SEC; } -#endif /* DRIVERS_STM32_I2C_H*/ +#endif /* __DRIVERS_STM32_I2C_H*/ diff --git a/core/include/drivers/stm32_iwdg.h b/core/include/drivers/stm32_iwdg.h index f1ad7345346de0ac0c15478954f5070e8a4bc7cb..a575a199daaefba66211afec219fe30ceba2b622 100644 --- a/core/include/drivers/stm32_iwdg.h +++ b/core/include/drivers/stm32_iwdg.h @@ -3,8 +3,8 @@ * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved */ -#ifndef DRIVERS_STM32_IWDG_H -#define DRIVERS_STM32_IWDG_H +#ifndef __DRIVERS_STM32_IWDG_H +#define __DRIVERS_STM32_IWDG_H #include <stdbool.h> @@ -26,8 +26,4 @@ struct stm32_iwdg_otp_data { */ TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, struct stm32_iwdg_otp_data *otp_data); - -/* Refresh all registered IWDG watchdog instance */ -void stm32_iwdg_refresh(void); - -#endif /*DRIVERS_STM32_IWDG_H*/ +#endif /*__DRIVERS_STM32_IWDG_H*/ diff --git a/core/include/drivers/stm32_remoteproc.h b/core/include/drivers/stm32_remoteproc.h new file mode 100644 index 0000000000000000000000000000000000000000..8cb1efd863ccecc0f1ddab2fea72739bce9a8b6e --- /dev/null +++ b/core/include/drivers/stm32_remoteproc.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DRIVERS_STM32_REMOTEPROC_H +#define __DRIVERS_STM32_REMOTEPROC_H + +#include <stdint.h> +#include <tee_api_types.h> +#include <types_ext.h> + +/* IDs of the supported remote processors*/ +#define STM32_M4_RPROC_ID 0 + +/* + * stm32_rproc_get() - get the rproc handle associated to a remote processor ID + * @rproc_id unique identifier of the remote processor + * Return a pointer to the rproc firmware handle related to @rproc_id or NULL. + */ +void *stm32_rproc_get(uint32_t rproc_id); + +/* + * stm32_rproc_da_to_pa() - Convert the coprocessor device address to a CPU + * physical address. + * @rproc_id unique identifier of the remote processor + * @da device memory address from the remote processor space + * perspective. + * @size size of the memory + * @pa Output CPU physical address associated to @da. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, + paddr_t *pa); + +/* + * stm32_rproc_map() - map the physical address if valid + * @rproc_id unique identifier of the remote processor + * @pa physical address from the CPU space perspective + * @size size of the memory + * @va Output CPU virtual address associated to @pa. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, + void **va); + +/* + * stm32_rproc_unmap() - ummap the virtual address mapped with stm32_rproc_map + * @rproc_id unique identifier of the remote processor + * @va virtual address + * @size size of the memory + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size); + +/* + * stm32_rproc_start() - start the remote processor core + * @rproc_id unique identifier of the remote processor + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_start(uint32_t rproc_id); + +/* + * stm32_rproc_stop() - stop the remote processor core + * @rproc_id unique identifier of the remote processor + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_stop(uint32_t rproc_id); + +#endif /* __DRIVERS_STM32_REMOTEPROC_H */ diff --git a/core/include/drivers/stm32_uart.h b/core/include/drivers/stm32_uart.h index 250737f339f81a3c5f7181275863a40f16777b06..6054df72c513f57ebfd02cebca7a1a79b2dd935c 100644 --- a/core/include/drivers/stm32_uart.h +++ b/core/include/drivers/stm32_uart.h @@ -3,8 +3,8 @@ * Copyright (c) 2017-2023, STMicroelectronics */ -#ifndef DRIVERS_STM32_UART_H -#define DRIVERS_STM32_UART_H +#ifndef __DRIVERS_STM32_UART_H +#define __DRIVERS_STM32_UART_H #include <drivers/clk.h> #include <drivers/pinctrl.h> @@ -42,4 +42,4 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base); */ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node); -#endif /*DRIVERS_STM32_UART_H*/ +#endif /*__DRIVERS_STM32_UART_H*/ diff --git a/core/include/drivers/stm32mp13_regulator_iod.h b/core/include/drivers/stm32mp13_regulator_iod.h new file mode 100644 index 0000000000000000000000000000000000000000..9cd70e37235ccb5ff4cd44291cd0cf578ad457ba --- /dev/null +++ b/core/include/drivers/stm32mp13_regulator_iod.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32MP13_REGULATOR_IOD_H +#define __DRIVERS_STM32MP13_REGULATOR_IOD_H + +#include <drivers/regulator.h> + +enum iod_regulator_id { + IOD_SDMMC1, + IOD_SDMMC2, + IOD_REGU_COUNT +}; + +#ifdef CFG_STM32MP13_REGULATOR_IOD +struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index); +#else +static inline struct regulator * +stm32mp1_get_iod_regulator(enum iod_regulator_id id __unused) { return NULL; } +#endif /* CFG_STM32MP13_REGULATOR_IOD */ +#endif /* __DRIVERS_STM32MP13_REGULATOR_IOD_H */ diff --git a/core/include/drivers/stm32mp_dt_bindings.h b/core/include/drivers/stm32mp_dt_bindings.h index 2d7a27cf2da5b6375dbc3aaf6985c0c5a547e30b..1c438ecefa4d4b178cb3263f18bd1a8defe26c61 100644 --- a/core/include/drivers/stm32mp_dt_bindings.h +++ b/core/include/drivers/stm32mp_dt_bindings.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2022, STMicroelectronics */ -#ifndef STM32MP_DT_BINDINGS_H -#define STM32MP_DT_BINDINGS_H +#ifndef __DRIVERS_STM32MP_DT_BINDINGS_H +#define __DRIVERS_STM32MP_DT_BINDINGS_H #ifdef CFG_STM32MP13 #include <dt-bindings/clock/stm32mp13-clks.h> @@ -18,4 +18,4 @@ #include <dt-bindings/reset/stm32mp1-resets.h> #endif -#endif /* STM32MP_DT_BINDINGS_H */ +#endif /* __DRIVERS_STM32MP_DT_BINDINGS_H */ diff --git a/core/include/drivers/stpmic1.h b/core/include/drivers/stpmic1.h index 0d020caedbb7c6b60945a6b33580c349ade14a3d..13539c6587c64edd5514bb55bd706b94d6561688 100644 --- a/core/include/drivers/stpmic1.h +++ b/core/include/drivers/stpmic1.h @@ -3,8 +3,8 @@ * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved */ -#ifndef __STPMIC1_H__ -#define __STPMIC1_H__ +#ifndef __DRIVERS_STPMIC1_H +#define __DRIVERS_STPMIC1_H #include <drivers/stm32_i2c.h> #include <util.h> @@ -241,4 +241,4 @@ int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, struct stpmic1_lp_cfg *cfg); int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg); -#endif /*__STPMIC1_H__*/ +#endif /*__DRIVERS_STPMIC1_H*/ diff --git a/core/include/drivers/wdt.h b/core/include/drivers/wdt.h index b07152e7b80724b63322a739f3a3eb60b1260bcc..8a22b5eb4de58fe5f73efaf5d501363b029aab3e 100644 --- a/core/include/drivers/wdt.h +++ b/core/include/drivers/wdt.h @@ -3,8 +3,8 @@ * Copyright 2019 Broadcom. */ -#ifndef DRIVERS_WDT_H -#define DRIVERS_WDT_H +#ifndef __DRIVERS_WDT_H +#define __DRIVERS_WDT_H #include <assert.h> #include <kernel/interrupt.h> @@ -117,4 +117,4 @@ enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused) } #endif -#endif /* DRIVERS_WDT_H */ +#endif /* __DRIVERS_WDT_H */ diff --git a/core/include/dt-bindings/gpio/stm32mp_gpio.h b/core/include/dt-bindings/gpio/stm32mp_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..3afcf415824620394a826730e396681dbedc0f7d --- /dev/null +++ b/core/include/dt-bindings/gpio/stm32mp_gpio.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_GPIO_STM32MP_GPIO_H +#define _DT_BINDINGS_GPIO_STM32MP_GPIO_H + +#include <dt-bindings/gpio/gpio.h> + +/* Macro to define the security for GPIO */ +#ifdef __ASSEMBLER__ +#define TZPROT(id) (1 << (id)) +#else +#define TZPROT(id) (UINT32_C(1) << (id)) +#endif + +#endif diff --git a/core/include/gen-asm-defines.h b/core/include/gen-asm-defines.h index ebf330f2092dfce4ec6b3ef64e3014aba43c4e28..8b612a539f0d3513f00114a5c2d86b132c18aa38 100644 --- a/core/include/gen-asm-defines.h +++ b/core/include/gen-asm-defines.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ -#ifndef GEN_ASM_DEFINES_H -#define GEN_ASM_DEFINES_H +#ifndef __GEN_ASM_DEFINES_H +#define __GEN_ASM_DEFINES_H #define DEFINES void __defines(void); void __defines(void) #define DEFINE(def, val) \ asm volatile("\n.ascii \"==>" #def " %c0 " #val "\"" : : "i" (val)); -#endif /*GEN_ASM_DEFINES_H*/ +#endif /*__GEN_ASM_DEFINES_H*/ diff --git a/core/include/initcall.h b/core/include/initcall.h index 28aa5ea75a1ad74af992964979f91076c3ecaa56..db3d95e2179139e4342d04c847dab71feb145aa8 100644 --- a/core/include/initcall.h +++ b/core/include/initcall.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef INITCALL_H -#define INITCALL_H +#ifndef __INITCALL_H +#define __INITCALL_H #include <scattered_array.h> #include <tee_api_types.h> diff --git a/core/include/io.h b/core/include/io.h index 85365ce7ac9de96d21f12496b5cbc2c081c3e23e..0ef91907b3423cd85da30449db9d31f50c6fecb0 100644 --- a/core/include/io.h +++ b/core/include/io.h @@ -2,10 +2,11 @@ /* * Copyright (c) 2014-2019, Linaro Limited */ -#ifndef IO_H -#define IO_H +#ifndef __IO_H +#define __IO_H #include <compiler.h> +#include <kernel/delay.h> #include <stdint.h> #include <types_ext.h> #include <utee_defines.h> @@ -300,4 +301,4 @@ static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, !(_cond); \ }) -#endif /*IO_H*/ +#endif /*__IO_H*/ diff --git a/core/include/keep.h b/core/include/keep.h index 0dbe91005fc7018610dc365fa8c791158273e4f9..622d1d65bbfc024d90c6b5e5e6864dd3302b0182 100644 --- a/core/include/keep.h +++ b/core/include/keep.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef KEEP_H -#define KEEP_H +#ifndef __KEEP_H +#define __KEEP_H #ifdef __ASSEMBLER__ @@ -45,4 +45,4 @@ #endif /* __ASSEMBLER__ */ -#endif /*KEEP_H*/ +#endif /*__KEEP_H*/ diff --git a/core/include/kernel/abort.h b/core/include/kernel/abort.h index ed0e5c0ca4b1000dd8a84393e04202abcb422764..4a0f5270d2c1ca58f479b9992de4054fcbdfeb4e 100644 --- a/core/include/kernel/abort.h +++ b/core/include/kernel/abort.h @@ -3,8 +3,8 @@ * Copyright (c) 2015-2021, Linaro Limited */ -#ifndef KERNEL_ABORT_H -#define KERNEL_ABORT_H +#ifndef __KERNEL_ABORT_H +#define __KERNEL_ABORT_H #define ABORT_TYPE_UNDEF 0 #define ABORT_TYPE_PREFETCH 1 @@ -40,5 +40,5 @@ bool abort_is_write_fault(struct abort_info *ai); void abort_print_current_ts(void); #endif /*__ASSEMBLER__*/ -#endif /*KERNEL_ABORT_H*/ +#endif /*__KERNEL_ABORT_H*/ diff --git a/core/include/kernel/boot.h b/core/include/kernel/boot.h index 14025b30cc2c774ab66952627ef51d2ba810c06c..bf78d5c3808fffef1911b27388cb0a50d7f28c01 100644 --- a/core/include/kernel/boot.h +++ b/core/include/kernel/boot.h @@ -42,12 +42,11 @@ struct boot_embdata { extern const struct core_mmu_config boot_mmu_config; -/* @nsec_entry is unused if using CFG_WITH_ARM_TRUSTED_FW */ -void boot_init_primary_early(unsigned long pageable_part, - unsigned long nsec_entry); +void boot_init_primary_early(void); void boot_init_primary_late(unsigned long fdt, unsigned long manifest); void boot_init_memtag(void); -void boot_save_boot_info(void *boot_info); +void boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4); void __panic_at_smc_return(void) __noreturn; @@ -96,10 +95,9 @@ void *get_manifest_dt(void); /* * get_aslr_seed() - return a random seed for core ASLR - * @fdt: Pointer to a device tree if CFG_DT_ADDR=y * * This function has a __weak default implementation. */ -unsigned long get_aslr_seed(void *fdt); +unsigned long get_aslr_seed(void); #endif /* __KERNEL_BOOT_H */ diff --git a/core/include/kernel/chip_services.h b/core/include/kernel/chip_services.h index a22237ce1987e7e47dd6436b29d42bf4d1cd2265..c051078f15c43a229036e336ad3e493d9ad277e2 100644 --- a/core/include/kernel/chip_services.h +++ b/core/include/kernel/chip_services.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef CHIP_SERVICES_H -#define CHIP_SERVICES_H +#ifndef __KERNEL_CHIP_SERVICES_H +#define __KERNEL_CHIP_SERVICES_H /* Die ID */ #define FVR_DIE_ID_NUM_REGS 3 diff --git a/core/include/kernel/dt.h b/core/include/kernel/dt.h index 7a7bd9afdccb0957cce95f50ae2656a99c7064ad..ad5cde23ab97bcbf2d9c36d654f4dfc615eafdf9 100644 --- a/core/include/kernel/dt.h +++ b/core/include/kernel/dt.h @@ -3,11 +3,10 @@ * Copyright (c) 2016-2021, Linaro Limited */ -#ifndef KERNEL_DT_H -#define KERNEL_DT_H +#ifndef __KERNEL_DT_H +#define __KERNEL_DT_H #include <compiler.h> -#include <kernel/interrupt.h> #include <kernel/panic.h> #include <scattered_array.h> #include <stdint.h> @@ -267,13 +266,14 @@ struct dt_descriptor *get_external_dt_desc(void); /* * init_external_dt() - Initialize the external DTB located at given address. * @phys_dt: Physical address where the external DTB located. + * @dt_sz: Maximum size of the external DTB. * * Initialize the external DTB. * * 1. Add MMU mapping of the external DTB, * 2. Initialize device tree overlay */ -void init_external_dt(unsigned long phys_dt); +void init_external_dt(unsigned long phys_dt, size_t dt_sz); /* Returns external DTB if present, otherwise NULL */ void *get_external_dt(void); @@ -420,7 +420,8 @@ static inline struct dt_descriptor *get_external_dt_desc(void) return NULL; } -static inline void init_external_dt(unsigned long phys_dt __unused) +static inline void init_external_dt(unsigned long phys_dt __unused, + size_t dt_sz __unused) { } @@ -445,4 +446,4 @@ static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused, } #endif /* !CFG_DT */ -#endif /* KERNEL_DT_H */ +#endif /* __KERNEL_DT_H */ diff --git a/core/include/kernel/dt_driver.h b/core/include/kernel/dt_driver.h index 38a934ad17e2840be7f482560b383ad8f839be1e..f73f30073acff86a635330e3788b8d985f9e406b 100644 --- a/core/include/kernel/dt_driver.h +++ b/core/include/kernel/dt_driver.h @@ -5,8 +5,8 @@ * Copyright (c) 2021, STMicroelectronics */ -#ifndef __DT_DRIVER_H -#define __DT_DRIVER_H +#ifndef __KERNEL_DT_DRIVER_H +#define __KERNEL_DT_DRIVER_H #include <kernel/dt.h> #include <stdint.h> @@ -25,6 +25,7 @@ * DT_DRIVER_PINCTRL Pin controller using generic reset DT bindings * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings + * DT_DRIVER_NVMEM NVMEM controller using generic NVMEM DT bindings */ enum dt_driver_type { DT_DRIVER_NOTYPE, @@ -36,6 +37,7 @@ enum dt_driver_type { DT_DRIVER_PINCTRL, DT_DRIVER_INTERRUPT, DT_DRIVER_REGULATOR, + DT_DRIVER_NVMEM, }; /* @@ -102,16 +104,16 @@ struct dt_pargs { * * @parg: phandle argument(s) referencing the device in the FDT. * @data: driver private data registered in struct dt_driver. - * @res: Output result code of the operation: - * TEE_SUCCESS in case of success - * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized - * Any TEE_Result compliant code in case of error. + * @device_ref: output device reference upon success, e.g. a struct clk + * pointer for a clock driver. * - * Return a device opaque reference, e.g. a struct clk pointer for a clock - * driver, or NULL if not found in which case @res provides the error code. + * Return code: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized + * Any TEE_Result compliant code in case of error. */ typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data, - void **out_device); + void *device_ref); /** * dt_driver_register_provider - Register a driver provider @@ -139,7 +141,7 @@ TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, * @nodeoffset: node offset in the FDT * @prop_idx: index of the phandle data in the property * @type: Driver type - * @out_device: output device opaque reference upon support, for example + * @device_ref: output device opaque reference upon support, for example * a struct clk pointer for a clock driver. * Return code: @@ -153,7 +155,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, const void *fdt, int nodeoffset, unsigned int prop_idx, enum dt_driver_type type, - void **out_device); + void *device_ref); /* * dt_driver_device_from_parent - Return a device instance based on the parent. @@ -163,7 +165,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, * @fdt: FDT base address * @nodeoffset: node offset in the FDT * @type: Driver type - * @dout_device: output device opaque reference upon success, for example + * @device_ref: output device opaque reference upon success, for example * a struct i2c_dev pointer for a I2C bus driver * * Return code: @@ -173,7 +175,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, */ TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, enum dt_driver_type type, - void **out_device); + void *device_ref); /* * dt_driver_device_from_node_idx_prop_phandle() - Same as @@ -190,7 +192,7 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, unsigned int prop_index, enum dt_driver_type type, uint32_t phandle, - void **out_device); + void *device_ref); /* * dt_driver_get_crypto() - Request crypto support for driver initialization @@ -278,5 +280,4 @@ static inline TEE_Result dt_driver_test_status(void) return TEE_ERROR_NOT_IMPLEMENTED; } #endif - -#endif /* __DT_DRIVER_H */ +#endif /* __KERNEL_DT_DRIVER_H */ diff --git a/core/include/kernel/early_ta.h b/core/include/kernel/early_ta.h index b7f9f38a696e1d5883b886d4f2cd043948c11b6d..8ad12e596385e2c6cd0d7b8f03e15e450d8ca4e2 100644 --- a/core/include/kernel/early_ta.h +++ b/core/include/kernel/early_ta.h @@ -3,8 +3,8 @@ * Copyright (c) 2017, 2020, Linaro Limited * Copyright (c) 2020, Arm Limited. */ -#ifndef KERNEL_EARLY_TA_H -#define KERNEL_EARLY_TA_H +#ifndef __KERNEL_EARLY_TA_H +#define __KERNEL_EARLY_TA_H #include <kernel/embedded_ts.h> #include <scattered_array.h> @@ -14,5 +14,5 @@ #define for_each_early_ta(_ta) \ SCATTERED_ARRAY_FOREACH(_ta, early_tas, struct embedded_ts) -#endif /* KERNEL_EARLY_TA_H */ +#endif /* __KERNEL_EARLY_TA_H */ diff --git a/core/include/kernel/embedded_ts.h b/core/include/kernel/embedded_ts.h index d2ae758b5b7a3213d3014c573f2ef2d4d0166206..aeaabffa215b5300d60bbde398b7af5f5619305f 100644 --- a/core/include/kernel/embedded_ts.h +++ b/core/include/kernel/embedded_ts.h @@ -3,8 +3,8 @@ * Copyright (c) 2017, Linaro Limited * Copyright (c) 2020, Arm Limited. */ -#ifndef KERNEL_EMBEDDED_TS_H -#define KERNEL_EMBEDDED_TS_H +#ifndef __KERNEL_EMBEDDED_TS_H +#define __KERNEL_EMBEDDED_TS_H #include <compiler.h> #include <kernel/linker.h> @@ -33,5 +33,5 @@ TEE_Result emb_ts_open(const TEE_UUID *uuid, TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size); TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len); -#endif /* KERNEL_EMBEDDED_TS_H */ +#endif /* __KERNEL_EMBEDDED_TS_H */ diff --git a/core/include/kernel/handle.h b/core/include/kernel/handle.h index eb4375dd3cf3a9149e09f89b6efbe468c1e5c4ac..9a7504d5c249d89c7905861f26224507fb1cc062 100644 --- a/core/include/kernel/handle.h +++ b/core/include/kernel/handle.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited * Copyright (c) 2020, Arm Limited */ -#ifndef KERNEL_HANDLE_H -#define KERNEL_HANDLE_H +#ifndef __KERNEL_HANDLE_H +#define __KERNEL_HANDLE_H #include <stdbool.h> #include <stdint.h> @@ -49,4 +49,4 @@ void *handle_put(struct handle_db *db, int handle); */ void *handle_lookup(struct handle_db *db, int handle); -#endif /*KERNEL_HANDLE_H*/ +#endif /*__KERNEL_HANDLE_H*/ diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h index c5b66a9b83a5731434fe181705e43dfbb4dce7c7..22a7a044945b5c353e1e18ff25a0b8f20997ef91 100644 --- a/core/include/kernel/interrupt.h +++ b/core/include/kernel/interrupt.h @@ -6,6 +6,7 @@ #define __KERNEL_INTERRUPT_H #include <dt-bindings/interrupt-controller/irq.h> +#include <kernel/dt_driver.h> #include <mm/core_memprot.h> #include <sys/queue.h> #include <tee_api_types.h> @@ -15,6 +16,11 @@ #define ITRF_TRIGGER_LEVEL BIT(0) #define ITRF_SHARED BIT(1) +/* Forward the interrupt only to the current CPU */ +#define ITR_CPU_MASK_TO_THIS_CPU BIT(31) +/* Forward the interrupt to all CPUs except the current CPU */ +#define ITR_CPU_MASK_TO_OTHER_CPUS BIT(30) + struct itr_handler; /* @@ -65,11 +71,25 @@ struct itr_ops { void (*unmask)(struct itr_chip *chip, size_t it); void (*raise_pi)(struct itr_chip *chip, size_t it); void (*raise_sgi)(struct itr_chip *chip, size_t it, - uint8_t cpu_mask); + uint32_t cpu_mask); void (*set_affinity)(struct itr_chip *chip, size_t it, uint8_t cpu_mask); }; +/* + * struct itr_desc - Interrupt description + * @chip Interrupt controller reference + * @itr_num Interrupt number + * + * This struct is used for binding interrupt device data between + * drivers when using DT_DRIVERS means. See itr_dt_get_func type + * definition. + */ +struct itr_desc { + struct itr_chip *chip; + size_t itr_num; +}; + /* Interrupt handler return value */ enum itr_return { ITRR_NONE, @@ -130,6 +150,8 @@ void interrupt_main_init(struct itr_chip *data); /* Retrieve main interrupt controller reference */ struct itr_chip *interrupt_get_main_chip(void); +/* Retrieve main interrupt controller reference, or NULL on failure */ +struct itr_chip *interrupt_get_main_chip_may_fail(void); #ifdef CFG_DT /* @@ -158,27 +180,6 @@ static inline int dt_get_irq(const void *fdt, int node) } #endif -struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, - uint32_t flags, void *data, - uint32_t type, uint32_t prio); -void itr_free(struct itr_handler *hdl); -void itr_add_type_prio(struct itr_handler *handler, uint32_t type, - uint32_t prio); -void itr_enable(size_t it); -void itr_disable(size_t it); -/* raise the Peripheral Interrupt corresponding to the interrupt ID */ -void itr_raise_pi(size_t it); -/* - * raise the Software Generated Interrupt corresponding to the interrupt ID, - * the cpu_mask represents which cpu interface to forward. - */ -void itr_raise_sgi(size_t it, uint8_t cpu_mask); -/* - * let corresponding interrupt forward to the cpu interface - * according to the cpu_mask. - */ -void itr_set_affinity(size_t it, uint8_t cpu_mask); - /* * __weak overridable function which is called when a secure interrupt is * received. The default function calls panic() immediately, platforms which @@ -186,19 +187,6 @@ void itr_set_affinity(size_t it, uint8_t cpu_mask); */ void interrupt_main_handler(void); -static inline void itr_add(struct itr_handler *handler) -{ - itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); -} - -static inline struct itr_handler *itr_alloc_add(size_t it, - itr_handler_t handler, - uint32_t flags, void *data) -{ - return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, - 0); -} - /* * Interrupt controller chip API functions */ @@ -300,10 +288,12 @@ static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller * @chip Interrupt controller * @itr_num Interrupt number to raise - * @cpu_mask Mask of the CPUs targeted by the interrupt + * @cpu_mask: A bitfield of CPUs to forward the interrupt to, unless + * ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS + * (mutually exclusive) are set. */ static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, - uint8_t cpu_mask) + uint32_t cpu_mask) { assert(interrupt_can_raise_sgi(chip)); chip->ops->raise_sgi(chip, itr_num, cpu_mask); @@ -357,6 +347,25 @@ static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); } +/* + * interrupt_create_handler() - Allocate/register an interrupt callback handler + * @itr_chip Interrupt chip obtained from dt_get_interrupt_by_*() + * @itr_num Interrupt number obtained from dt_get_interrupt_by_*() + * @callback Callback handler function + * @priv Private dat to pssa to @callback + * @flags INTERRUPT_FLAGS_* or 0 + * @out_hdl Output allocated and registered handler or NULL + * + * This function differs from interrupt_add_handler() in that the + * interrupt is not reconfigured. interrupt_create_handler() expects + * @itr_desc was obtained from a call to dt_get_interrupt_by_index() + * or dt_get_interrupt_by_name(). That call configured the interrupt. + */ +TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, + itr_handler_t callback, void *priv, + uint32_t flags, + struct itr_handler **out_hdl); + /* * interrupt_add_handler_with_chip() - Register an interrupt handler providing * the interrupt chip reference in specific argument @chip. @@ -426,4 +435,110 @@ static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, * This function may panic on non-NULL invalid @hdl reference. */ void interrupt_remove_free_handler(struct itr_handler *hdl); + +/* + * itr_dt_get_func - Typedef of function to get an interrupt in DT node + * + * @args Reference to phandle arguments + * @data Pointer to data given at interrupt_register_provider() call + * @itr_desc_p Pointer to the struct itr_desc to fill + * Return TEE_SUCCESS in case of success. + * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized. + * Return another TEE_Result code otherwise. + * + * Upon success, the interrupt is configured and consumer can add a handler + * function to the interrupt. Yet, the interrupt is not enabled until consumer + * calls interrupt_enable(). + */ +typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data, + struct itr_desc *itr_desc_p); + +#ifdef CFG_DT +/** + * interrupt_register_provider() - Register an interrupt provider + * + * @fdt Device tree to work on + * @node Node offset of the interrupt controller in the DT + * @dt_get_itr Callback to match the devicetree interrupt reference with + * @data Data which will be passed to the get_dt_its callback + */ +TEE_Result interrupt_register_provider(const void *fdt, int node, + itr_dt_get_func dt_get_itr, void *data); + +/** + * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index + * + * Interrupt index (@index) refers to the index of the target interrupt to be + * retrieved as DT binding property "interrupts" may define several + * interrupts. + * + * @fdt Device tree to work on + * @node Node offset of the subnode containing interrupt(s) references + * @index Index in "interrupts" or "extended-interrupts" property list + * @chip Output interrupt controller reference upon success + * @itr_num Output interrupt number upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, + unsigned int index, struct itr_chip **chip, + size_t *itr_num); + +/** + * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name + * + * @fdt Device tree to work on + * @node Node offset of the subnode containing interrupt(s) references + * @name Name identifier used in "interrupt-names" property + * @chip Output interrupt controller reference upon success + * @itr_num Output interrupt number upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, + struct itr_chip **chip, size_t *itr_num); +#else +static inline TEE_Result interrupt_register_provider(const void *dt __unused, + int node __unused, + itr_dt_get_func f __unused, + void *data __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused, + int node __unused, + unsigned int index __unused, + struct itr_chip **c __unused, + size_t *itr_num __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused, + int node __unused, + const char *name __unused, + struct itr_chip **ch __unused, + size_t *itr_num __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /*CFG_DT*/ + +/* + * Helper function for when caller retrieves the first interrupt defined + * in "interrupts" or "extended-interrupts" DT binding property list. + */ +static inline TEE_Result interrupt_dt_get(const void *fdt, int node, + struct itr_chip **chip, + size_t *itr_num) +{ + return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); +} #endif /*__KERNEL_INTERRUPT_H*/ diff --git a/core/include/kernel/ldelf_loader.h b/core/include/kernel/ldelf_loader.h index 4d5e92c6f8f94b7ba1f5f3524df782bdfe05ee96..fef590cd0f75ecc896d926921c60c76e5ab296cd 100644 --- a/core/include/kernel/ldelf_loader.h +++ b/core/include/kernel/ldelf_loader.h @@ -7,8 +7,8 @@ #include <kernel/user_mode_ctx.h> #include <tee_api_types.h> -#ifndef KERNEL_LDELF_LOADER_H -#define KERNEL_LDELF_LOADER_H +#ifndef __KERNEL_LDELF_LOADER_H +#define __KERNEL_LDELF_LOADER_H TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx); TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, @@ -21,4 +21,4 @@ TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, const char *sym, size_t symlen, vaddr_t *val); -#endif /* KERNEL_LDELF_LOADER_H */ +#endif /* __KERNEL_LDELF_LOADER_H */ diff --git a/core/include/kernel/ldelf_syscalls.h b/core/include/kernel/ldelf_syscalls.h index 5dd89a7f23dccf7d365f10b7733b1f271b7eb4ce..62b410ad78a92cabec1edc588ff689366afe4b18 100644 --- a/core/include/kernel/ldelf_syscalls.h +++ b/core/include/kernel/ldelf_syscalls.h @@ -11,8 +11,8 @@ #include <tee_api_types.h> #include <types_ext.h> -#ifndef KERNEL_LDELF_SYSCALLS_H -#define KERNEL_LDELF_SYSCALLS_H +#ifndef __KERNEL_LDELF_SYSCALLS_H +#define __KERNEL_LDELF_SYSCALLS_H struct system_ctx { struct handle_db db; @@ -39,4 +39,4 @@ TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va, TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes); void ldelf_sess_cleanup(struct ts_session *sess); -#endif /* KERNEL_LDELF_SYSCALLS_H */ +#endif /* __KERNEL_LDELF_SYSCALLS_H */ diff --git a/core/include/kernel/misc.h b/core/include/kernel/misc.h index 35cfa5f133ab6b39e268b8c3c1b63a090e05f941..d204a3ae7a626a8e203bc4fac8ea1000566d4678 100644 --- a/core/include/kernel/misc.h +++ b/core/include/kernel/misc.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef KERNEL_MISC_H -#define KERNEL_MISC_H +#ifndef __KERNEL_MISC_H +#define __KERNEL_MISC_H #include <assert.h> #include <kernel/misc_arch.h> @@ -23,4 +23,4 @@ static inline size_t __noprof get_core_pos(void) return __get_core_pos(); } -#endif /*KERNEL_MISC_H*/ +#endif /*__KERNEL_MISC_H*/ diff --git a/core/include/kernel/msg_param.h b/core/include/kernel/msg_param.h index 841c3bfa4e7742df6e7a7a7e4d4ecb3535c9bb2a..2cf3da657d39901a4c7dcfca241bb8a3feb5d5b7 100644 --- a/core/include/kernel/msg_param.h +++ b/core/include/kernel/msg_param.h @@ -26,8 +26,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef KERNEL_MSG_PARAM_H -#define KERNEL_MSG_PARAM_H +#ifndef __KERNEL_MSG_PARAM_H +#define __KERNEL_MSG_PARAM_H #include <compiler.h> #include <kernel/msg_param.h> @@ -81,4 +81,4 @@ static inline bool msg_param_attr_is_tmem(uint64_t attr) } } -#endif /*KERNEL_MSG_PARAM_H*/ +#endif /*__KERNEL_MSG_PARAM_H*/ diff --git a/core/include/kernel/mutex.h b/core/include/kernel/mutex.h index e4c470b0f15f837857c410964dbde6be57f270bc..c701188d79c274ceb7185f76443d86253baf43fd 100644 --- a/core/include/kernel/mutex.h +++ b/core/include/kernel/mutex.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014-2017, Linaro Limited */ -#ifndef KERNEL_MUTEX_H -#define KERNEL_MUTEX_H +#ifndef __KERNEL_MUTEX_H +#define __KERNEL_MUTEX_H #include <kernel/refcount.h> #include <kernel/wait_queue.h> @@ -101,5 +101,5 @@ void condvar_broadcast(struct condvar *cv); void condvar_wait(struct condvar *cv, struct mutex *m); #endif -#endif /*KERNEL_MUTEX_H*/ +#endif /*__KERNEL_MUTEX_H*/ diff --git a/core/include/kernel/panic.h b/core/include/kernel/panic.h index 9dc38dce13f7faf4e00f66ab887476b42008b713..3d4fa55b248a8873b0011c518dfa1bd0a28feeab 100644 --- a/core/include/kernel/panic.h +++ b/core/include/kernel/panic.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef KERNEL_PANIC_H -#define KERNEL_PANIC_H +#ifndef __KERNEL_PANIC_H +#define __KERNEL_PANIC_H #include <compiler.h> @@ -39,4 +39,4 @@ void __do_panic(const char *file, const int line, const char *func, */ void cpu_idle(void); -#endif /*KERNEL_PANIC_H*/ +#endif /*__KERNEL_PANIC_H*/ diff --git a/core/include/kernel/pseudo_ta.h b/core/include/kernel/pseudo_ta.h index 132c59f11e4201e01d0e528ab4a8c408f757045a..965ca0d4364d4bfcdfa25f5fa96149907460b71a 100644 --- a/core/include/kernel/pseudo_ta.h +++ b/core/include/kernel/pseudo_ta.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef KERNEL_PSEUDO_TA_H -#define KERNEL_PSEUDO_TA_H +#ifndef __KERNEL_PSEUDO_TA_H +#define __KERNEL_PSEUDO_TA_H #include <assert.h> #include <compiler.h> @@ -95,5 +95,5 @@ TEE_Result from_bounce_params(uint32_t param_types, TEE_Param bparams[TEE_NUM_PARAMS], TEE_Param *eparams); -#endif /* KERNEL_PSEUDO_TA_H */ +#endif /* __KERNEL_PSEUDO_TA_H */ diff --git a/core/include/kernel/rpc_io_i2c.h b/core/include/kernel/rpc_io_i2c.h index 50ddbcd4dd2f32a5d153f2aadfbc2ddae601e388..fe9f6b8e6726eec3a17db7ea8bdae28c1ca58863 100644 --- a/core/include/kernel/rpc_io_i2c.h +++ b/core/include/kernel/rpc_io_i2c.h @@ -3,8 +3,8 @@ * Copyright (c) 2020 Foundries Ltd <jorge@foundries.io> */ -#ifndef __RPC_IO_I2C_H -#define __RPC_IO_I2C_H +#ifndef __KERNEL_RPC_IO_I2C_H +#define __KERNEL_RPC_IO_I2C_H #include <optee_rpc_cmd.h> #include <tee_api_types.h> @@ -35,4 +35,4 @@ struct rpc_i2c_request { TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes); -#endif /* __RPC_IO_I2C_H */ +#endif /* __KERNEL_RPC_IO_I2C_H */ diff --git a/core/include/kernel/spinlock.h b/core/include/kernel/spinlock.h index fc3e2e474f82e5245133d38ac8ac71dc62dbd62c..e7a84d32b678f404e81d0ee726803457a17118df 100644 --- a/core/include/kernel/spinlock.h +++ b/core/include/kernel/spinlock.h @@ -4,8 +4,8 @@ * Copyright (c) 2016, Linaro Limited */ -#ifndef KERNEL_SPINLOCK_H -#define KERNEL_SPINLOCK_H +#ifndef __KERNEL_SPINLOCK_H +#define __KERNEL_SPINLOCK_H #define SPINLOCK_LOCK 1 #define SPINLOCK_UNLOCK 0 @@ -129,4 +129,4 @@ static inline void cpu_spin_unlock_xrestore(unsigned int *lock, } #endif /* __ASSEMBLER__ */ -#endif /* KERNEL_SPINLOCK_H */ +#endif /* __KERNEL_SPINLOCK_H */ diff --git a/core/include/kernel/tee_common.h b/core/include/kernel/tee_common.h index 5c5da2d6e4c5c86e6391f856f697c795faa3a61d..d4b0672107b8f7b640bff2a11189cebebd220ea5 100644 --- a/core/include/kernel/tee_common.h +++ b/core/include/kernel/tee_common.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_COMMON_H -#define TEE_COMMON_H +#ifndef __KERNEL_TEE_COMMON_H +#define __KERNEL_TEE_COMMON_H #include <stdlib.h> @@ -35,4 +35,4 @@ void tee_mtime_perftest(void); #define tee_mtime_perftest() do { } while (0) #endif -#endif /* TEE_COMMON_H */ +#endif /* __KERNEL_TEE_COMMON_H */ diff --git a/core/include/kernel/tee_common_otp.h b/core/include/kernel/tee_common_otp.h index 2b0d3a3a209d9020c13eb989bb3c05e01b9f07f4..cc1f0a88bb3457f960545949d6034ad6dbeefd54 100644 --- a/core/include/kernel/tee_common_otp.h +++ b/core/include/kernel/tee_common_otp.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_COMMON_OTP_H -#define TEE_COMMON_OTP_H +#ifndef __KERNEL_TEE_COMMON_OTP_H +#define __KERNEL_TEE_COMMON_OTP_H #include <stddef.h> #include <stdint.h> @@ -20,4 +20,4 @@ int tee_otp_get_die_id(uint8_t *buffer, size_t len); TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer, size_t len); -#endif /* TEE_COMMON_OTP_H */ +#endif /* __KERNEL_TEE_COMMON_OTP_H */ diff --git a/core/include/kernel/tee_misc.h b/core/include/kernel/tee_misc.h index 035acd37f6b38765637ee318635d708410b94fa8..66552520247c37924103a478c9513bfaa06a1c11 100644 --- a/core/include/kernel/tee_misc.h +++ b/core/include/kernel/tee_misc.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_MISC_H -#define TEE_MISC_H +#ifndef __KERNEL_TEE_MISC_H +#define __KERNEL_TEE_MISC_H #include <types_ext.h> @@ -68,4 +68,4 @@ bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl, */ void *alloc_cache_aligned(size_t size); -#endif /* TEE_MISC_H */ +#endif /* __KERNEL_TEE_MISC_H */ diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h index ef689b5205406592d53fb8f48c2a95eff5d5afb6..8cae35002e19df258cd6613860dfeb5e688703ca 100644 --- a/core/include/kernel/tee_ta_manager.h +++ b/core/include/kernel/tee_ta_manager.h @@ -5,8 +5,8 @@ * Copyright (c) 2020, Arm Limited */ -#ifndef TEE_TA_MANAGER_H -#define TEE_TA_MANAGER_H +#ifndef __KERNEL_TEE_TA_MANAGER_H +#define __KERNEL_TEE_TA_MANAGER_H #include <assert.h> #include <kernel/mutex.h> diff --git a/core/include/kernel/tee_time.h b/core/include/kernel/tee_time.h index 396155104725c52c151fdad126121dd5faf550c2..28b41545c4e5dcdddb7801ed75c9d25a34f8555f 100644 --- a/core/include/kernel/tee_time.h +++ b/core/include/kernel/tee_time.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_TIME_H -#define TEE_TIME_H +#ifndef __KERNEL_TEE_TIME_H +#define __KERNEL_TEE_TIME_H #include "tee_api_types.h" diff --git a/core/include/kernel/thread.h b/core/include/kernel/thread.h index 022aeec58f09b85ba08dfd75e97cd38fd1602687..b7f497e1091188582bb56493eaa1077831e25ab5 100644 --- a/core/include/kernel/thread.h +++ b/core/include/kernel/thread.h @@ -5,8 +5,8 @@ * Copyright (c) 2020-2021, Arm Limited */ -#ifndef KERNEL_THREAD_H -#define KERNEL_THREAD_H +#ifndef __KERNEL_THREAD_H +#define __KERNEL_THREAD_H #ifndef __ASSEMBLER__ #include <types_ext.h> @@ -396,4 +396,4 @@ void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user, #endif /*__ASSEMBLER__*/ -#endif /*KERNEL_THREAD_H*/ +#endif /*__KERNEL_THREAD_H*/ diff --git a/core/include/kernel/time_source.h b/core/include/kernel/time_source.h index fce5391a0ff8e0ef55ab71f97c9bb09c278bf9bc..e02f98432a320f2012315ac6ab9ea7d2838f0ef2 100644 --- a/core/include/kernel/time_source.h +++ b/core/include/kernel/time_source.h @@ -2,6 +2,8 @@ /* * Copyright (c) 2014, Linaro Limited */ +#ifndef __KERNEL_TIME_SOURCE_H +#define __KERNEL_TIME_SOURCE_H #include <kernel/tee_time.h> @@ -18,3 +20,4 @@ void time_source_init(void); } extern struct time_source _time_source; +#endif /*__KERNEL_TIME_SOURCE_H*/ diff --git a/core/include/kernel/timer.h b/core/include/kernel/timer.h index 8aaca449a6d7777d803798f7ec9a033974f7f0d7..19abd115bd376a91dbd9620fc0f1b91b787cbb49 100644 --- a/core/include/kernel/timer.h +++ b/core/include/kernel/timer.h @@ -3,8 +3,8 @@ * Copyright (C) 2018, Linaro Limited */ -#ifndef __TIMER_H -#define __TIMER_H +#ifndef __KERNEL_TIMER_H +#define __KERNEL_TIMER_H void generic_timer_start(uint32_t time_ms); void generic_timer_stop(void); @@ -12,4 +12,4 @@ void generic_timer_stop(void); /* Handler for timer expiry interrupt */ void generic_timer_handler(uint32_t time_ms); -#endif /* __TIMER_H */ +#endif /* __KERNEL_TIMER_H */ diff --git a/core/include/kernel/trace_ta.h b/core/include/kernel/trace_ta.h index 44644e660bd6946ac9a656d85d6187b000fa215c..96ced9f375f18cb6651a7f48940fc6bafb43e379 100644 --- a/core/include/kernel/trace_ta.h +++ b/core/include/kernel/trace_ta.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, Linaro Limited */ -#ifndef TRACE_TA_H -#define TRACE_TA_H +#ifndef __KERNEL_TRACE_TA_H +#define __KERNEL_TRACE_TA_H #include <trace.h> @@ -16,5 +16,5 @@ #define TAMSG_RAW(...) #endif -#endif /*TRACE_TA_H*/ +#endif /*__KERNEL_TRACE_TA_H*/ diff --git a/core/include/kernel/transfer_list.h b/core/include/kernel/transfer_list.h new file mode 100644 index 0000000000000000000000000000000000000000..ed813979f289ede1a78218a25c2fa10eb463b374 --- /dev/null +++ b/core/include/kernel/transfer_list.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef __KERNEL_TRANSFER_LIST_H +#define __KERNEL_TRANSFER_LIST_H + +#define TRANSFER_LIST_SIGNATURE U(0x4a0fb10b) +#define TRANSFER_LIST_VERSION U(0x0001) + +/* + * Init value of maximum alignment required by any transfer entry data in the TL + * specified as a power of two + */ +#define TRANSFER_LIST_INIT_MAX_ALIGN U(3) + +/* Alignment required by transfer entry header start address, in bytes */ +#define TRANSFER_LIST_GRANULE U(8) + +/* + * Version of the register convention used. + * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9 + */ +#define REG_CONVENTION_VER_MASK BIT(24) + +#define TL_FLAGS_HAS_CHECKSUM BIT(0) + +/* Transfer list operation codes */ +#define TL_OPS_NONE U(0) /* invalid for any operation */ +#define TL_OPS_ALL U(1) /* valid for all operations */ +#define TL_OPS_RO U(2) /* valid for read only */ +#define TL_OPS_CUS U(3) /* either abort or special code to interpret */ + +#ifndef __ASSEMBLER__ + +#include <types_ext.h> + +/* Get alignment from a value specified as power of two */ +#define TL_ALIGNMENT_FROM_ORDER(a) BIT(a) + +enum transfer_list_tag_id { + TL_TAG_EMPTY = 0, + TL_TAG_FDT = 1, + TL_TAG_HOB_BLOCK = 2, + TL_TAG_HOB_LIST = 3, + TL_TAG_ACPI_TABLE_AGGREGATE = 4, + TL_TAG_OPTEE_PAGABLE_PART = 0x100, +}; + +struct transfer_list_header { + uint32_t signature; + uint8_t checksum; + uint8_t version; + uint8_t hdr_size; + uint8_t alignment; /* max alignment of transfer entry data */ + uint32_t size; /* TL header + all transfer entries */ + uint32_t max_size; + uint32_t flags; + uint32_t reserved; /* spare bytes */ + /* + * Commented out element used to visualize dynamic part of the + * data structure. + * + * Note that struct transfer_list_entry also is dynamic in size + * so the elements can't be indexed directly but instead must be + * traversed in order + * + * struct transfer_list_entry entries[]; + */ +}; + +struct transfer_list_entry { + uint16_t tag_id; + uint8_t reserved0; /* place holder for tag ID 3rd byte (MSB) */ + uint8_t hdr_size; + uint32_t data_size; + /* + * Commented out element used to visualize dynamic part of the + * data structure. + * + * Note that padding is added at the end of @data to make it reach + * a 8-byte boundary. + * + * uint8_t data[ROUNDUP(data_size, 8)]; + */ +}; + +struct transfer_list_header *transfer_list_map(paddr_t pa); +void transfer_list_unmap_sync(struct transfer_list_header *tl); +void transfer_list_unmap_nosync(struct transfer_list_header *tl); + +void transfer_list_dump(struct transfer_list_header *tl); +struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size); + +struct transfer_list_header * +transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, + size_t max_size); + +#if defined(CFG_TRANSFER_LIST) + +int transfer_list_check_header(const struct transfer_list_header *tl); + +struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, + uint16_t tag_id); + +void *transfer_list_entry_data(struct transfer_list_entry *tl_e); + +#else /* CFG_TRANSFER_LIST */ + +static inline int +transfer_list_check_header(const struct transfer_list_header *tl __unused) +{ + return TL_OPS_NONE; +} + +static inline struct transfer_list_entry * +transfer_list_find(struct transfer_list_header *tl __unused, + uint16_t tag_id __unused) +{ + return NULL; +} + +static inline void * +transfer_list_entry_data(struct transfer_list_entry *tl_e __unused) +{ + return NULL; +} + +#endif /* CFG_TRANSFER_LIST */ + +void transfer_list_update_checksum(struct transfer_list_header *tl); +bool transfer_list_verify_checksum(const struct transfer_list_header *tl); + +bool transfer_list_set_data_size(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e, + uint32_t new_data_size); + +bool transfer_list_rem(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e); + +struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, + uint16_t tag_id, + uint32_t data_size, + const void *data); + +struct transfer_list_entry * +transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, + uint32_t data_size, const void *data, + uint8_t alignment); + +struct transfer_list_entry * +transfer_list_next(struct transfer_list_header *tl, + struct transfer_list_entry *last); + +#endif /*__ASSEMBLER__*/ +#endif /*__TRANSFER_LIST_H*/ diff --git a/core/include/kernel/unwind.h b/core/include/kernel/unwind.h index 9a01b4613c8781afe00c9881e5dcf1a7dd07ab7b..8ecf3435940676af4f07874ef846c875ee3c7aa1 100644 --- a/core/include/kernel/unwind.h +++ b/core/include/kernel/unwind.h @@ -4,8 +4,8 @@ * Copyright (c) 2020, Huawei Technologies Co., Ltd */ -#ifndef KERNEL_UNWIND -#define KERNEL_UNWIND +#ifndef __KERNEL_UNWIND +#define __KERNEL_UNWIND #include <types_ext.h> @@ -27,4 +27,4 @@ static inline void *unw_get_kernel_stack(void) } #endif /* CFG_UNWIND */ -#endif /*KERNEL_UNWIND*/ +#endif /*__KERNEL_UNWIND*/ diff --git a/core/include/kernel/user_ta.h b/core/include/kernel/user_ta.h index 942c948f6704527942d54b167e297a7f1aebbd24..667122b5c675a2d09eaa1f91c248e3bc3a5f54cd 100644 --- a/core/include/kernel/user_ta.h +++ b/core/include/kernel/user_ta.h @@ -3,8 +3,8 @@ * Copyright (c) 2015, Linaro Limited * Copyright (c) 2020, Arm Limited */ -#ifndef KERNEL_USER_TA_H -#define KERNEL_USER_TA_H +#ifndef __KERNEL_USER_TA_H +#define __KERNEL_USER_TA_H #include <assert.h> #include <kernel/tee_ta_manager.h> @@ -70,4 +70,4 @@ static inline TEE_Result tee_ta_init_user_ta_session( #endif -#endif /*KERNEL_USER_TA_H*/ +#endif /*__KERNEL_USER_TA_H*/ diff --git a/core/include/kernel/virtualization.h b/core/include/kernel/virtualization.h index c4a7f69fe7ed0c04f2744d2d15faa6442870fc9f..f14904e564d474e704356326a4fd29d49653c935 100644 --- a/core/include/kernel/virtualization.h +++ b/core/include/kernel/virtualization.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, EPAM Systems. All rights reserved. */ -#ifndef KERNEL_VIRTUALIZATION_H -#define KERNEL_VIRTUALIZATION_H +#ifndef __KERNEL_VIRTUALIZATION_H +#define __KERNEL_VIRTUALIZATION_H #include <mm/core_mmu.h> #include <stdbool.h> @@ -135,4 +135,4 @@ static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) { return 0; } #endif -#endif /* KERNEL_VIRTUALIZATION_H */ +#endif /* __KERNEL_VIRTUALIZATION_H */ diff --git a/core/include/kernel/wait_queue.h b/core/include/kernel/wait_queue.h index a13c02b6c65198c38c23a47b84191ee3dc9e2850..20691e7fee0d17a05e92b9f0ada54293226177a4 100644 --- a/core/include/kernel/wait_queue.h +++ b/core/include/kernel/wait_queue.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef KERNEL_WAIT_QUEUE_H -#define KERNEL_WAIT_QUEUE_H +#ifndef __KERNEL_WAIT_QUEUE_H +#define __KERNEL_WAIT_QUEUE_H #include <types_ext.h> #include <sys/queue.h> @@ -60,5 +60,5 @@ void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv, int lineno); bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv); -#endif /*KERNEL_WAIT_QUEUE_H*/ +#endif /*__KERNEL_WAIT_QUEUE_H*/ diff --git a/core/include/mm/core_memprot.h b/core/include/mm/core_memprot.h index d809ad30593efecfe3b5f9bb1e27df9b7fd57d6b..428c827b270bbe9da0912829f2614381128c1df5 100644 --- a/core/include/mm/core_memprot.h +++ b/core/include/mm/core_memprot.h @@ -3,8 +3,8 @@ * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef CORE_MEMPROT_H -#define CORE_MEMPROT_H +#ifndef __MM_CORE_MEMPROT_H +#define __MM_CORE_MEMPROT_H #include <mm/core_mmu.h> #include <types_ext.h> @@ -115,4 +115,4 @@ vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len); vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len); vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len); -#endif /* CORE_MEMPROT_H */ +#endif /* __MM_CORE_MEMPROT_H */ diff --git a/core/include/mm/core_mmu.h b/core/include/mm/core_mmu.h index c6f258631256e3a71d43c0299a2fc4e406e84c4d..b239c6fbf65b9f62f79f976054962be31efc4a47 100644 --- a/core/include/mm/core_mmu.h +++ b/core/include/mm/core_mmu.h @@ -3,8 +3,8 @@ * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef CORE_MMU_H -#define CORE_MMU_H +#ifndef __MM_CORE_MMU_H +#define __MM_CORE_MMU_H #ifndef __ASSEMBLER__ #include <assert.h> @@ -73,10 +73,12 @@ * MEM_AREA_NEX_NSEC_SHM: nexus non-secure shared RAM between NSec and TEE. * MEM_AREA_RAM_NSEC: NonSecure RAM storing data * MEM_AREA_RAM_SEC: Secure RAM storing some secrets + * MEM_AREA_ROM_SEC: Secure read only memory storing some secrets * MEM_AREA_IO_NSEC: NonSecure HW mapped registers * MEM_AREA_IO_SEC: Secure HW mapped registers * MEM_AREA_EXT_DT: Memory loads external device tree * MEM_AREA_MANIFEST_DT: Memory loads manifest device tree + * MEM_AREA_TRANSFER_LIST: Memory area mapped for Transfer List * MEM_AREA_RES_VASPACE: Reserved virtual memory space * MEM_AREA_SHM_VASPACE: Virtual memory space for dynamic shared memory buffers * MEM_AREA_TS_VASPACE: TS va space, only used with phys_to_virt() @@ -102,10 +104,12 @@ enum teecore_memtypes { MEM_AREA_NEX_NSEC_SHM, MEM_AREA_RAM_NSEC, MEM_AREA_RAM_SEC, + MEM_AREA_ROM_SEC, MEM_AREA_IO_NSEC, MEM_AREA_IO_SEC, MEM_AREA_EXT_DT, MEM_AREA_MANIFEST_DT, + MEM_AREA_TRANSFER_LIST, MEM_AREA_RES_VASPACE, MEM_AREA_SHM_VASPACE, MEM_AREA_TS_VASPACE, @@ -136,10 +140,12 @@ static inline const char *teecore_memtype_name(enum teecore_memtypes type) [MEM_AREA_NEX_NSEC_SHM] = "NEX_NSEC_SHM", [MEM_AREA_RAM_NSEC] = "RAM_NSEC", [MEM_AREA_RAM_SEC] = "RAM_SEC", + [MEM_AREA_ROM_SEC] = "ROM_SEC", [MEM_AREA_IO_NSEC] = "IO_NSEC", [MEM_AREA_IO_SEC] = "IO_SEC", [MEM_AREA_EXT_DT] = "EXT_DT", [MEM_AREA_MANIFEST_DT] = "MANIFEST_DT", + [MEM_AREA_TRANSFER_LIST] = "TRANSFER_LIST", [MEM_AREA_RES_VASPACE] = "RES_VASPACE", [MEM_AREA_SHM_VASPACE] = "SHM_VASPACE", [MEM_AREA_TS_VASPACE] = "TS_VASPACE", @@ -689,4 +695,4 @@ void core_mmu_get_ta_range(paddr_t *base, size_t *size); #endif /*__ASSEMBLER__*/ -#endif /* CORE_MMU_H */ +#endif /* __MM_CORE_MMU_H */ diff --git a/core/include/mm/pgt_cache.h b/core/include/mm/pgt_cache.h index 13cd9b2104ea2b4807e19965e4120fe402e9f24b..4f3e37e26c81974881de7494c8627d4f00344629 100644 --- a/core/include/mm/pgt_cache.h +++ b/core/include/mm/pgt_cache.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2016, Linaro Limited */ -#ifndef MM_PGT_CACHE_H -#define MM_PGT_CACHE_H +#ifndef __MM_PGT_CACHE_H +#define __MM_PGT_CACHE_H #ifdef CFG_WITH_LPAE #define PGT_SIZE (4 * 1024) @@ -136,4 +136,4 @@ static inline void pgt_set_used_entries(struct pgt *pgt __unused, #endif -#endif /*MM_PGT_CACHE_H*/ +#endif /*__MM_PGT_CACHE_H*/ diff --git a/core/include/mm/tee_mm.h b/core/include/mm/tee_mm.h index 481f583754d0098d0708cbaa15ef7b979e91e45c..aae35f8717acc6b13f856f34367f21d838fe562d 100644 --- a/core/include/mm/tee_mm.h +++ b/core/include/mm/tee_mm.h @@ -3,10 +3,11 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_MM_H -#define TEE_MM_H +#ifndef __MM_TEE_MM_H +#define __MM_TEE_MM_H #include <malloc.h> +#include <pta_stats.h> #include <types_ext.h> /* Define to indicate default pool initiation */ @@ -112,7 +113,7 @@ bool tee_mm_addr_is_within_range(const tee_mm_pool_t *pool, paddr_t addr); bool tee_mm_is_empty(tee_mm_pool_t *pool); #ifdef CFG_WITH_STATS -void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats, +void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats, bool reset); #endif diff --git a/core/include/mm/tee_mmu_types.h b/core/include/mm/tee_mmu_types.h index e643d27f44227e737fe6d3b572f9325dedf512cd..2f495910f0eceb20c134459e20e948f3cfefc780 100644 --- a/core/include/mm/tee_mmu_types.h +++ b/core/include/mm/tee_mmu_types.h @@ -4,8 +4,8 @@ * Copyright (c) 2021, Linaro Limited * Copyright (c) 2022, Arm Limited. */ -#ifndef TEE_MMU_TYPES_H -#define TEE_MMU_TYPES_H +#ifndef __MM_TEE_MMU_TYPES_H +#define __MM_TEE_MMU_TYPES_H #include <stdint.h> #include <sys/queue.h> diff --git a/core/include/mm/tee_pager.h b/core/include/mm/tee_pager.h index 4e42e64eb5e7de02f18e8ad9a33594216b716db6..3c5b63017470000ea7627d8061bd79ec9f5f385d 100644 --- a/core/include/mm/tee_pager.h +++ b/core/include/mm/tee_pager.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef MM_TEE_PAGER_H -#define MM_TEE_PAGER_H +#ifndef __MM_TEE_PAGER_H +#define __MM_TEE_PAGER_H #include <kernel/abort.h> #include <kernel/panic.h> diff --git a/core/include/mm/vm.h b/core/include/mm/vm.h index f1509ba5d8a6712fcbcf052b69aa4b1541d4c296..16bafe8f0043f475ffc526c594fc07e6778d1c11 100644 --- a/core/include/mm/vm.h +++ b/core/include/mm/vm.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_MMU_H -#define TEE_MMU_H +#ifndef __MM_VM_H +#define __MM_VM_H #include <tee_api_types.h> #include <kernel/tee_ta_manager.h> @@ -97,4 +97,4 @@ void vm_set_ctx(struct ts_ctx *ctx); struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len, uint16_t *prot, size_t *offs); -#endif /*TEE_MMU_H*/ +#endif /*__MM_VM_H*/ diff --git a/core/include/optee_msg.h b/core/include/optee_msg.h index 7cc795d746e04dce3c1492bcf09d79acf67e5137..5fa626b0eb6a77186330c3f70712fde4bb426b54 100644 --- a/core/include/optee_msg.h +++ b/core/include/optee_msg.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015-2020, Linaro Limited */ -#ifndef _OPTEE_MSG_H -#define _OPTEE_MSG_H +#ifndef __OPTEE_MSG_H +#define __OPTEE_MSG_H #include <compiler.h> #include <types_ext.h> @@ -342,4 +342,4 @@ struct optee_msg_arg { #define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF U(7) #define OPTEE_MSG_FUNCID_CALL_WITH_ARG U(0x0004) -#endif /* _OPTEE_MSG_H */ +#endif /* __OPTEE_MSG_H */ diff --git a/core/include/signed_hdr.h b/core/include/signed_hdr.h index edeb446cc233fe418e3a36d3671a8e32d30e5476..0aacd8feea294ac5b9c3ae6d13286c411504c5ac 100644 --- a/core/include/signed_hdr.h +++ b/core/include/signed_hdr.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef SIGNED_HDR_H -#define SIGNED_HDR_H +#ifndef __SIGNED_HDR_H +#define __SIGNED_HDR_H #include <inttypes.h> #include <stdlib.h> @@ -225,4 +225,4 @@ TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, */ TEE_Result shdr_verify_signature(const struct shdr *shdr); -#endif /*SIGNED_HDR_H*/ +#endif /*__SIGNED_HDR_H*/ diff --git a/core/include/ta_pub_key.h b/core/include/ta_pub_key.h index 1259e014d6060496d9ed41e61e4776711eab4569..dc02a6f17f7e4a1f8cf067021e5dde1192b1fe9e 100644 --- a/core/include/ta_pub_key.h +++ b/core/include/ta_pub_key.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef KERNEL_TA_PUB_KEY_H -#define KERNEL_TA_PUB_KEY_H +#ifndef __TA_PUB_KEY_H +#define __TA_PUB_KEY_H #include <types_ext.h> @@ -11,5 +11,5 @@ extern const uint32_t ta_pub_key_exponent; extern const uint8_t ta_pub_key_modulus[]; extern const size_t ta_pub_key_modulus_size; -#endif /*KERNEL_TA_PUB_KEY_H*/ +#endif /*__TA_PUB_KEY_H*/ diff --git a/core/include/tee/cache.h b/core/include/tee/cache.h index 568b2515ed7dbca9ee47e1f2819f91b5d75771d2..cb412104e66e448124aa69574ffb6de6e2059c03 100644 --- a/core/include/tee/cache.h +++ b/core/include/tee/cache.h @@ -2,11 +2,11 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef TEE_CACHE_H -#define TEE_CACHE_H +#ifndef __TEE_CACHE_H +#define __TEE_CACHE_H #include <utee_types.h> TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len); -#endif /* TEE_CACHE_H */ +#endif /* __TEE_CACHE_H */ diff --git a/core/include/tee/entry_std.h b/core/include/tee/entry_std.h index d228badeba6167e893ece6d74ca6dee35c9d1492..d9ddb6200a949e81f957e393d79f5799e21f7a58 100644 --- a/core/include/tee/entry_std.h +++ b/core/include/tee/entry_std.h @@ -4,8 +4,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_ENTRY_STD_H -#define TEE_ENTRY_STD_H +#ifndef __TEE_ENTRY_STD_H +#define __TEE_ENTRY_STD_H #include <kernel/thread.h> #include <optee_msg.h> @@ -23,4 +23,4 @@ TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params); /* Get list head for sessions opened from non-secure */ void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions); -#endif /* TEE_ENTRY_STD_H */ +#endif /* __TEE_ENTRY_STD_H */ diff --git a/core/include/tee/svc_cache.h b/core/include/tee/svc_cache.h index a2bccde371c570f7f12243c780ef33e67ac2a09b..56321edd912c884473a5e11331f081f745316966 100644 --- a/core/include/tee/svc_cache.h +++ b/core/include/tee/svc_cache.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2015, Linaro Limited */ -#ifndef SVC_CACHE_H -#define SVC_CACHE_H +#ifndef __TEE_SVC_CACHE_H +#define __TEE_SVC_CACHE_H #include <types_ext.h> #include <tee_api_types.h> @@ -14,4 +14,4 @@ TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op); #define syscall_cache_operation syscall_not_supported #endif -#endif /*SVC_CACHE_H*/ +#endif /*__TEE_SVC_CACHE_H*/ diff --git a/core/include/tee/tee_cryp_concat_kdf.h b/core/include/tee/tee_cryp_concat_kdf.h index 49d3348f5b4628301365e42914d71aee8cfcb39f..dbcca313531f58f92346b19b0a4f3e286419064d 100644 --- a/core/include/tee/tee_cryp_concat_kdf.h +++ b/core/include/tee/tee_cryp_concat_kdf.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEE_CRYP_CONCAT_KDF_H -#define TEE_CRYP_CONCAT_KDF_H +#ifndef __TEE_TEE_CRYP_CONCAT_KDF_H +#define __TEE_TEE_CRYP_CONCAT_KDF_H #include <tee_api_types.h> @@ -14,4 +14,4 @@ TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len); -#endif /* TEE_CRYP_CONCAT_KDF_H */ +#endif /* __TEE_TEE_CRYP_CONCAT_KDF_H */ diff --git a/core/include/tee/tee_cryp_hkdf.h b/core/include/tee/tee_cryp_hkdf.h index be0703e42080d1038c0f1742f00e8209badaf7f8..adce9d893057335dd11d42dbdd6ebf958d6d518d 100644 --- a/core/include/tee/tee_cryp_hkdf.h +++ b/core/include/tee/tee_cryp_hkdf.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEE_CRYP_HKDF_H -#define TEE_CRYP_HKDF_H +#ifndef __TEE_TEE_CRYP_HKDF_H +#define __TEE_TEE_CRYP_HKDF_H #include <tee_api_types.h> @@ -13,4 +13,4 @@ TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, const uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len); -#endif /* TEE_CRYP_HKDF_H */ +#endif /* __TEE_TEE_CRYP_HKDF_H */ diff --git a/core/include/tee/tee_cryp_pbkdf2.h b/core/include/tee/tee_cryp_pbkdf2.h index 81b7beb1af35c3b43dd707fc260fd449a2fe05e2..d141032647fcb19d17210e00c3b072b257ddcb32 100644 --- a/core/include/tee/tee_cryp_pbkdf2.h +++ b/core/include/tee/tee_cryp_pbkdf2.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEE_CRYP_PBKDF2_H -#define TEE_CRYP_PBKDF2_H +#ifndef __TEE_TEE_CRYP_PBKDF2_H +#define __TEE_TEE_CRYP_PBKDF2_H #include <tee_api_types.h> @@ -13,4 +13,4 @@ TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, size_t salt_len, uint32_t iteration_count, uint8_t *derived_key, size_t derived_key_len); -#endif /* TEE_CRYP_PBKDF2_H */ +#endif /* __TEE_TEE_CRYP_PBKDF2_H */ diff --git a/core/include/tee/tee_cryp_utl.h b/core/include/tee/tee_cryp_utl.h index 98a694a0510ef319c9fac5595ea8187783aace42..7259cc3d6e93ef8fe55f6ac4ad18b2a631d09508 100644 --- a/core/include/tee/tee_cryp_utl.h +++ b/core/include/tee/tee_cryp_utl.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, Linaro Limited */ -#ifndef TEE_CRYP_UTL_H -#define TEE_CRYP_UTL_H +#ifndef __TEE_TEE_CRYP_UTL_H +#define __TEE_TEE_CRYP_UTL_H #include <tee_api_types.h> #include <crypto/crypto.h> diff --git a/core/include/tee/tee_fs.h b/core/include/tee/tee_fs.h index 1b632d7ad4b0d80f1eb47bbce5f67839bcbb9af4..fce494c6bea3571b71d9bf6a71e5a192c00996cb 100644 --- a/core/include/tee/tee_fs.h +++ b/core/include/tee/tee_fs.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_FS_H -#define TEE_FS_H +#ifndef __TEE_TEE_FS_H +#define __TEE_TEE_FS_H #include <stddef.h> #include <stdint.h> @@ -99,4 +99,4 @@ tee_svc_storage_file_ops(uint32_t storage_id) } } -#endif /*TEE_FS_H*/ +#endif /*__TEE_TEE_FS_H*/ diff --git a/core/include/tee/tee_fs_key_manager.h b/core/include/tee/tee_fs_key_manager.h index ac5763043556d5d20e7c2df409e695f23affacfd..736dedf55e484fc18bf4d011de15e614d827c288 100644 --- a/core/include/tee/tee_fs_key_manager.h +++ b/core/include/tee/tee_fs_key_manager.h @@ -3,8 +3,8 @@ * Copyright (c) 2015, Linaro Limited */ -#ifndef TEE_FS_KEY_MANAGER_H -#define TEE_FS_KEY_MANAGER_H +#ifndef __TEE_TEE_FS_KEY_MANAGER_H +#define __TEE_TEE_FS_KEY_MANAGER_H #include <tee_api_types.h> #include <utee_defines.h> diff --git a/core/include/tee/tee_fs_rpc.h b/core/include/tee/tee_fs_rpc.h index ae49682c9ca7e3a5752f14d1ff80ccf260634683..88132952c2072d6d8dcfca27b08240b07384209a 100644 --- a/core/include/tee/tee_fs_rpc.h +++ b/core/include/tee/tee_fs_rpc.h @@ -7,8 +7,8 @@ * Interface with tee-supplicant for file operations */ -#ifndef TEE_FS_RPC_H -#define TEE_FS_RPC_H +#ifndef __TEE_TEE_FS_RPC_H +#define __TEE_TEE_FS_RPC_H #include <stdbool.h> #include <stddef.h> @@ -46,4 +46,4 @@ TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op); TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len); TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh); -#endif /* TEE_FS_RPC_H */ +#endif /* __TEE_TEE_FS_RPC_H */ diff --git a/core/include/tee/tee_obj.h b/core/include/tee/tee_obj.h index adbe543157daf33148a29377af1c5f65ffab0ed5..1c23dc065c17b0a89b9fdc43f0da5a7d5769eaa4 100644 --- a/core/include/tee/tee_obj.h +++ b/core/include/tee/tee_obj.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_OBJ_H -#define TEE_OBJ_H +#ifndef __TEE_TEE_OBJ_H +#define __TEE_TEE_OBJ_H #include <kernel/tee_ta_manager.h> #include <sys/queue.h> diff --git a/core/include/tee/tee_pobj.h b/core/include/tee/tee_pobj.h index bd05da4edffa84b9bc8b6311325e7544ea9970aa..8fcd792acc76f675389fb9502beeebb31005a502 100644 --- a/core/include/tee/tee_pobj.h +++ b/core/include/tee/tee_pobj.h @@ -3,8 +3,8 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_POBJ_H -#define TEE_POBJ_H +#ifndef __TEE_TEE_POBJ_H +#define __TEE_TEE_POBJ_H #include <stdint.h> #include <sys/queue.h> @@ -18,6 +18,7 @@ struct tee_pobj { void *obj_id; uint32_t obj_id_len; uint32_t flags; + uint32_t obj_info_usage; bool temporary; /* can be changed while creating == true */ bool creating; /* can only be changed with mutex held */ /* Filesystem handling this object */ @@ -43,4 +44,11 @@ TEE_Result tee_pobj_release(struct tee_pobj *obj); TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, uint32_t obj_id_len); +/* + * Locks and unlocks a mutex intended to protect the obj_info_usage field + * in struct tee_pobj. + */ +void tee_pobj_lock_usage(struct tee_pobj *obj); +void tee_pobj_unlock_usage(struct tee_pobj *obj); + #endif diff --git a/core/include/tee/tee_supp_plugin_rpc.h b/core/include/tee/tee_supp_plugin_rpc.h index 2d725c9d0651963cb26f1fcceab61f06ddfb54bc..5e4688a2457ddab057cdc8ddf22ea4d2390f858a 100644 --- a/core/include/tee/tee_supp_plugin_rpc.h +++ b/core/include/tee/tee_supp_plugin_rpc.h @@ -3,8 +3,8 @@ * Copyright (c) 2020, Open Mobile Platform LLC */ -#ifndef TEE_SUPP_PLUGIN_RPC_H -#define TEE_SUPP_PLUGIN_RPC_H +#ifndef __TEE_TEE_SUPP_PLUGIN_RPC_H +#define __TEE_TEE_SUPP_PLUGIN_RPC_H #include <stdint.h> #include <stdbool.h> @@ -15,4 +15,4 @@ TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, void *buf_user, size_t len, size_t *outlen); -#endif /* TEE_SUPP_PLUGIN_RPC_H */ +#endif /* __TEE_TEE_SUPP_PLUGIN_RPC_H */ diff --git a/core/include/tee/tee_svc.h b/core/include/tee/tee_svc.h index 27a04c05dd1b363ecf10c56f47943592ac81307b..7c1476567faef20c6a434e13f29a77c8a7c8651b 100644 --- a/core/include/tee/tee_svc.h +++ b/core/include/tee/tee_svc.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_SVC_H -#define TEE_SVC_H +#ifndef __TEE_TEE_SVC_H +#define __TEE_TEE_SVC_H #include <kernel/ts_manager.h> #include <stdint.h> @@ -74,4 +74,4 @@ TEE_Result syscall_wait(unsigned long timeout); TEE_Result syscall_get_time(unsigned long cat, TEE_Time *time); TEE_Result syscall_set_ta_time(const TEE_Time *time); -#endif /* TEE_SVC_H */ +#endif /* __TEE_TEE_SVC_H */ diff --git a/core/include/tee/tee_svc_cryp.h b/core/include/tee/tee_svc_cryp.h index 3932cdf6aa7d84ce72d04b29afbf996602797abe..526d6e69842f244f50591e591d1e9e196511ec86 100644 --- a/core/include/tee/tee_svc_cryp.h +++ b/core/include/tee/tee_svc_cryp.h @@ -2,8 +2,8 @@ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ -#ifndef TEE_SVC_CRYP_H -#define TEE_SVC_CRYP_H +#ifndef __TEE_TEE_SVC_CRYP_H +#define __TEE_TEE_SVC_CRYP_H #include <tee_api_types.h> #include <utee_types.h> @@ -93,4 +93,4 @@ TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data, size_t data_len); TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src); -#endif /* TEE_SVC_CRYP_H */ +#endif /* __TEE_TEE_SVC_CRYP_H */ diff --git a/core/include/tee/tee_svc_storage.h b/core/include/tee/tee_svc_storage.h index c5d763ade40375917ad2c06c5e577f2ad11b850c..d30fce96ddf0bc14926b80dfe78f21ee79c7c7cd 100644 --- a/core/include/tee/tee_svc_storage.h +++ b/core/include/tee/tee_svc_storage.h @@ -1,14 +1,16 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2023, Linaro Limited */ -#ifndef TEE_SVC_STORAGE_H -#define TEE_SVC_STORAGE_H +#ifndef __TEE_TEE_SVC_STORAGE_H +#define __TEE_TEE_SVC_STORAGE_H -#include <tee_api_types.h> #include <kernel/tee_ta_manager.h> +#include <tee_api_types.h> #include <tee/tee_fs.h> +#include <tee/tee_obj.h> /* * Persistant Object Functions @@ -58,7 +60,8 @@ TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, unsigned long whence); void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc); +TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage); void tee_svc_storage_init(void); -#endif /* TEE_SVC_STORAGE_H */ +#endif /* __TEE_TEE_SVC_STORAGE_H */ diff --git a/core/include/tee/tee_ta_enc_manager.h b/core/include/tee/tee_ta_enc_manager.h index 5e1b2e5c98f8ec47a71a3e331ccf8c3e831901a1..e258679d37c71eb82209b611acd3dc053539c3fe 100644 --- a/core/include/tee/tee_ta_enc_manager.h +++ b/core/include/tee/tee_ta_enc_manager.h @@ -3,8 +3,8 @@ * Copyright (c) 2019, Linaro Limited */ -#ifndef TEE_TA_ENC_MANAGER_H -#define TEE_TA_ENC_MANAGER_H +#ifndef __TEE_TEE_TA_ENC_MANAGER_H +#define __TEE_TEE_TA_ENC_MANAGER_H #include <signed_hdr.h> #include <tee_api_types.h> diff --git a/core/kernel/dt.c b/core/kernel/dt.c index 299aba110175c2a7191b470453e4bf60632c03ab..722fabb7d2fd6b61f79f2c0ecb8c7e8ad07c0cb7 100644 --- a/core/kernel/dt.c +++ b/core/kernel/dt.c @@ -544,16 +544,16 @@ struct dt_descriptor *get_external_dt_desc(void) return &external_dt; } -void init_external_dt(unsigned long phys_dt) +void init_external_dt(unsigned long phys_dt, size_t dt_sz) { struct dt_descriptor *dt = &external_dt; - void *fdt = NULL; int ret = 0; + enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; if (!IS_ENABLED(CFG_EXTERNAL_DT)) return; - if (!phys_dt) { + if (!phys_dt || !dt_sz) { /* * No need to panic as we're not using the DT in OP-TEE * yet, we're only adding some nodes for normal world use. @@ -566,20 +566,31 @@ void init_external_dt(unsigned long phys_dt) return; } - fdt = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, CFG_DTB_MAX_SIZE); - if (!fdt) - panic("Failed to map external DTB"); - - dt->blob = fdt; + mtype = core_mmu_get_type_by_pa(phys_dt); + if (mtype == MEM_AREA_MAXTYPE) { + /* Map the DTB if it is not yet mapped */ + dt->blob = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, + dt_sz); + if (!dt->blob) + panic("Failed to map external DTB"); + } else { + /* Get the DTB address if already mapped in a memory area */ + dt->blob = phys_to_virt(phys_dt, mtype, dt_sz); + if (!dt->blob) { + EMSG("Failed to get a mapped external DTB for PA %#lx", + phys_dt); + panic(); + } + } - ret = init_dt_overlay(dt, CFG_DTB_MAX_SIZE); + ret = init_dt_overlay(dt, dt_sz); if (ret < 0) { EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt, ret); panic(); } - ret = fdt_open_into(fdt, fdt, CFG_DTB_MAX_SIZE); + ret = fdt_open_into(dt->blob, dt->blob, dt_sz); if (ret < 0) { EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret); panic(); @@ -600,6 +611,7 @@ void *get_external_dt(void) static TEE_Result release_external_dt(void) { int ret = 0; + paddr_t pa_dt = 0; if (!IS_ENABLED(CFG_EXTERNAL_DT)) return TEE_SUCCESS; @@ -607,6 +619,14 @@ static TEE_Result release_external_dt(void) if (!external_dt.blob) return TEE_SUCCESS; + pa_dt = virt_to_phys(external_dt.blob); + /* + * Skip packing and un-mapping operations if the external DTB is mapped + * in a different memory area + */ + if (core_mmu_get_type_by_pa(pa_dt) != MEM_AREA_EXT_DT) + return TEE_SUCCESS; + ret = fdt_pack(external_dt.blob); if (ret < 0) { EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d", diff --git a/core/kernel/dt_driver.c b/core/kernel/dt_driver.c index 256aefa9058f9f1a0cc7eeafd9930bd8002e1481..4597bf221a716139173525c271d894aac3818890 100644 --- a/core/kernel/dt_driver.c +++ b/core/kernel/dt_driver.c @@ -111,6 +111,7 @@ static void assert_type_is_valid(enum dt_driver_type type) case DT_DRIVER_PINCTRL: case DT_DRIVER_INTERRUPT: case DT_DRIVER_REGULATOR: + case DT_DRIVER_NVMEM: return; default: assert(0); @@ -163,6 +164,7 @@ static bool dt_driver_use_parent_controller(enum dt_driver_type type) { switch (type) { case DT_DRIVER_PINCTRL: + case DT_DRIVER_NVMEM: return true; default: return false; @@ -249,7 +251,8 @@ dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type) static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv, const void *fdt, int phandle_node, - const uint32_t *prop, void **device) + const uint32_t *prop, + void *device_ref) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_pargs *pargs = NULL; @@ -264,9 +267,9 @@ static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv, pargs->phandle_node = phandle_node; pargs->args_count = prv->provider_cells; for (n = 0; n < prv->provider_cells; n++) - pargs->args[n] = fdt32_to_cpu(prop[n + 1]); + pargs->args[n] = fdt32_to_cpu(prop[n]); - res = prv->get_of_device(pargs, prv->priv_data, device); + res = prv->get_of_device(pargs, prv->priv_data, device_ref); free(pargs); @@ -274,7 +277,8 @@ static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv, } TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, - enum dt_driver_type type, void **device) + enum dt_driver_type type, + void *device_ref) { int parent = -1; struct dt_driver_provider *prv = NULL; @@ -291,7 +295,8 @@ TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, return TEE_ERROR_DEFER_DRIVER_INIT; } - return device_from_provider_prop(prv, fdt, nodeoffset, NULL, device); + return device_from_provider_prop(prv, fdt, nodeoffset, NULL, + device_ref); } TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, @@ -300,7 +305,7 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, unsigned int prop_index, enum dt_driver_type type, uint32_t phandle, - void **device) + void *device_ref) { int len = 0; const uint32_t *prop = NULL; @@ -328,14 +333,14 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, return TEE_ERROR_ITEM_NOT_FOUND; return device_from_provider_prop(prv, fdt, phandle_node_unused, - prop + prop_index, device); + prop + prop_index, device_ref); } TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, const void *fdt, int nodeoffset, unsigned int prop_idx, enum dt_driver_type type, - void **device) + void *device_ref) { int len = 0; int idx = 0; @@ -380,23 +385,50 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, return TEE_ERROR_GENERIC; prv = dt_driver_get_provider_by_node(nodeoffset, type); - if (!prv) - return TEE_ERROR_DEFER_DRIVER_INIT; } else { prv = dt_driver_get_provider_by_phandle(phandle, type); - if (!prv) - return TEE_ERROR_DEFER_DRIVER_INIT; } - prv_cells = dt_driver_provider_cells(prv); + if (prv) { + prv_cells = dt_driver_provider_cells(prv); + } else if (prop_idx) { + /* + * When we need to skip another provider phandle + * arguments cells (aka when prop_idx != 0), we don't + * really need the skipped provider to be already + * registered, we can look straight in its DT node. + */ + phandle_node = fdt_node_offset_by_phandle(fdt, phandle); + if (phandle_node < 0) { + DMSG("Can't find node for phandle %"PRIu32, + phandle); + return TEE_ERROR_GENERIC; + } + + prv_cells = fdt_get_dt_driver_cells(fdt, phandle_node, + type); + if (prv_cells < 0) { + DMSG("Can't find cells count on node %s: %d", + fdt_get_name(fdt, phandle_node, NULL), + prv_cells); + return TEE_ERROR_GENERIC; + } + } + if (prop_idx) { prop_idx--; idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); continue; } + if (!prv) + return TEE_ERROR_DEFER_DRIVER_INIT; + + /* Skip property cell with the phandle, already handled */ + idx32++; + return device_from_provider_prop(prv, fdt, phandle_node, - prop + idx32, device); + prop + idx32, device_ref); } return TEE_ERROR_ITEM_NOT_FOUND; @@ -654,7 +686,7 @@ static TEE_Result add_node_to_probe(const void *fdt, int node, if (!elt) return TEE_ERROR_OUT_OF_MEMORY; - DMSG("element: %s on node %s", node_name, drv_name); + DMSG("element: %s on node %s", drv_name, node_name); memcpy(elt, &elt_new, sizeof(*elt)); diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c index 9fbc9b2b0099c6f8380352482ab6eb4772adb682..4fe92bd552322ab18f7b64fccfc2a6b78bf5c6de 100644 --- a/core/kernel/interrupt.c +++ b/core/kernel/interrupt.c @@ -46,6 +46,11 @@ struct itr_chip *interrupt_get_main_chip(void) return itr_main_chip; } +struct itr_chip *interrupt_get_main_chip_may_fail(void) +{ + return itr_main_chip; +} + #ifdef CFG_DT int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, uint32_t *prio) @@ -65,72 +70,6 @@ int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, } #endif -struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, - uint32_t flags, void *data, - uint32_t type, uint32_t prio) -{ - struct itr_handler *hdl = calloc(1, sizeof(*hdl)); - - if (hdl) { - hdl->it = it; - hdl->handler = handler; - hdl->flags = flags; - hdl->data = data; - itr_add_type_prio(hdl, type, prio); - } - - return hdl; -} - -void itr_free(struct itr_handler *hdl) -{ - if (!hdl) - return; - - itr_main_chip->ops->disable(itr_main_chip, hdl->it); - - SLIST_REMOVE(&itr_main_chip->handlers, hdl, itr_handler, link); - free(hdl); -} - -void itr_add_type_prio(struct itr_handler *h, uint32_t type, uint32_t prio) -{ - struct itr_handler __maybe_unused *hdl = NULL; - - SLIST_FOREACH(hdl, &itr_main_chip->handlers, link) - if (hdl->it == h->it) - assert((hdl->flags & ITRF_SHARED) && - (h->flags & ITRF_SHARED)); - - itr_main_chip->ops->add(itr_main_chip, h->it, type, prio); - SLIST_INSERT_HEAD(&itr_main_chip->handlers, h, link); -} - -void itr_enable(size_t it) -{ - itr_main_chip->ops->enable(itr_main_chip, it); -} - -void itr_disable(size_t it) -{ - itr_main_chip->ops->disable(itr_main_chip, it); -} - -void itr_raise_pi(size_t it) -{ - itr_main_chip->ops->raise_pi(itr_main_chip, it); -} - -void itr_raise_sgi(size_t it, uint8_t cpu_mask) -{ - itr_main_chip->ops->raise_sgi(itr_main_chip, it, cpu_mask); -} - -void itr_set_affinity(size_t it, uint8_t cpu_mask) -{ - itr_main_chip->ops->set_affinity(itr_main_chip, it, cpu_mask); -} - /* This function is supposed to be overridden in platform specific code */ void __weak __noreturn interrupt_main_handler(void) { @@ -170,8 +109,9 @@ TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, return TEE_SUCCESS; } -TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, - uint32_t type, uint32_t prio) +static TEE_Result add_configure_handler(struct itr_handler *hdl, + uint32_t type, uint32_t prio, + bool configure) { struct itr_handler *h = NULL; @@ -188,13 +128,52 @@ TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, } } - interrupt_configure(hdl->chip, hdl->it, type, prio); + if (configure) + interrupt_configure(hdl->chip, hdl->it, type, prio); SLIST_INSERT_HEAD(&hdl->chip->handlers, hdl, link); return TEE_SUCCESS; } +TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, + uint32_t type, uint32_t prio) +{ + return add_configure_handler(hdl, type, prio, true /* configure */); +} + +TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, + itr_handler_t callback, void *priv, + uint32_t flags, + struct itr_handler **out_hdl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_handler *itr_hdl = NULL; + + itr_hdl = calloc(1, sizeof(*itr_hdl)); + if (!itr_hdl) + return TEE_ERROR_OUT_OF_MEMORY; + + *itr_hdl = (struct itr_handler){ + .chip = itr_chip, + .it = itr_num, + .flags = flags, + .handler = callback, + .data = priv, + }; + + res = add_configure_handler(itr_hdl, 0, 0, false /* configure */); + if (res) { + free(itr_hdl); + return res; + } + + if (out_hdl) + *out_hdl = itr_hdl; + + return TEE_SUCCESS; +} + void interrupt_remove_handler(struct itr_handler *hdl) { struct itr_handler *h = NULL; @@ -262,3 +241,112 @@ void interrupt_remove_free_handler(struct itr_handler *hdl) free(hdl); } } + +#ifdef CFG_DT +TEE_Result interrupt_register_provider(const void *fdt, int node, + itr_dt_get_func dt_get_itr, void *data) +{ + return dt_driver_register_provider(fdt, node, + (get_of_device_func)dt_get_itr, + data, DT_DRIVER_INTERRUPT); +} + +/* + * Fills an itr_desc reference based on "interrupts" property bindings. + * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found but + * not yet initialized. + */ +static TEE_Result get_legacy_interrupt_by_index(const void *fdt, int node, + unsigned int index, + struct itr_desc *itr_desc) +{ + const uint32_t *prop = NULL; + uint32_t phandle = 0; + int pnode = 0; + int len = 0; + + prop = fdt_getprop(fdt, node, "interrupts", &len); + if (!prop) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Find "interrupt-parent" in node or its parents */ + pnode = node; + prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); + + while (!prop) { + pnode = fdt_parent_offset(fdt, pnode); + if (pnode < 0) + break; + + prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); + if (!prop && len != -FDT_ERR_NOTFOUND) + break; + } + if (!prop) { + DMSG("No interrupt parent for node %s", + fdt_get_name(fdt, node, NULL)); + return TEE_ERROR_GENERIC; + } + + /* "interrupt-parent" provides interrupt controller phandle */ + phandle = fdt32_to_cpu(prop[0]); + + /* Get interrupt chip/number from phandle and "interrupts" property */ + return dt_driver_device_from_node_idx_prop_phandle("interrupts", fdt, + node, index, + DT_DRIVER_INTERRUPT, + phandle, + itr_desc); +} + +/* + * Fills an itr_desc based on "interrupts-extended" property bindings. + * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found + * but not yet initialized. + */ +static TEE_Result get_extended_interrupt_by_index(const void *fdt, int node, + unsigned int index, + struct itr_desc *itr_desc) +{ + return dt_driver_device_from_node_idx_prop("interrupts-extended", + fdt, node, index, + DT_DRIVER_INTERRUPT, + itr_desc); +} + +TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, + unsigned int index, struct itr_chip **chip, + size_t *itr_num) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_desc desc = { }; + + assert(chip && itr_num); + + /* "interrupts-extended" takes precedence over "interrupts" */ + if (fdt_getprop(fdt, node, "interrupts-extended", NULL)) + res = get_extended_interrupt_by_index(fdt, node, index, &desc); + else + res = get_legacy_interrupt_by_index(fdt, node, index, &desc); + + if (!res) { + assert(desc.chip); + *chip = desc.chip; + *itr_num = desc.itr_num; + } + + return res; +} + +TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, + struct itr_chip **chip, size_t *itr_num) +{ + int idx = 0; + + idx = fdt_stringlist_search(fdt, node, "interrupt-names", name); + if (idx < 0) + return TEE_ERROR_GENERIC; + + return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num); +} +#endif /*CFG_DT*/ diff --git a/core/kernel/notif.c b/core/kernel/notif.c index 7ecc246fdf57f013299bb9e2faedcf6c1f12eaaa..d23b4fcd816b65ac471ade4da1575e716d5788ff 100644 --- a/core/kernel/notif.c +++ b/core/kernel/notif.c @@ -1,11 +1,8 @@ // SPDX-License-Identifier: BSD-2-Clause /* - * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2021-2023, Linaro Limited */ -#include <bitstring.h> -#include <drivers/gic.h> -#include <kernel/interrupt.h> #include <kernel/mutex.h> #include <kernel/notif.h> #include <kernel/spinlock.h> @@ -16,95 +13,12 @@ #if defined(CFG_CORE_ASYNC_NOTIF) static struct mutex notif_mutex = MUTEX_INITIALIZER; static unsigned int notif_lock = SPINLOCK_UNLOCK; +static bool notif_started; SLIST_HEAD(notif_driver_head, notif_driver); static struct notif_driver_head notif_driver_head = SLIST_HEAD_INITIALIZER(¬if_driver_head); -static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); -static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); -static bool notif_started; - -TEE_Result notif_alloc_async_value(uint32_t *val) -{ - static bool alloc_values_inited; - uint32_t old_itr_status = 0; - int bit = 0; - - old_itr_status = cpu_spin_lock_xsave(¬if_lock); - - if (!alloc_values_inited) { - bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); - alloc_values_inited = true; - } - - bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); - if (bit >= 0) { - *val = bit; - bit_set(notif_alloc_values, bit); - } - - cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); - - if (bit < 0) - return TEE_ERROR_OUT_OF_MEMORY; - - return TEE_SUCCESS; -} - -void notif_free_async_value(uint32_t val) -{ - uint32_t old_itr_status = 0; - - old_itr_status = cpu_spin_lock_xsave(¬if_lock); - - assert(val < NOTIF_ASYNC_VALUE_MAX); - assert(bit_test(notif_alloc_values, val)); - bit_clear(notif_alloc_values, val); - - cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); -} - -uint32_t notif_get_value(bool *value_valid, bool *value_pending) -{ - uint32_t old_itr_status = 0; - uint32_t res = 0; - int bit = 0; - - old_itr_status = cpu_spin_lock_xsave(¬if_lock); - - bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); - *value_valid = (bit >= 0); - if (!*value_valid) { - *value_pending = false; - goto out; - } - - res = bit; - bit_clear(notif_values, res); - bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); - *value_pending = (bit >= 0); -out: - cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); - - return res; -} - -void notif_send_async(uint32_t value) -{ - uint32_t old_itr_status = 0; - - static_assert(CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_PPI_BASE); - - assert(value <= NOTIF_ASYNC_VALUE_MAX); - old_itr_status = cpu_spin_lock_xsave(¬if_lock); - - DMSG("0x%"PRIx32, value); - bit_set(notif_values, value); - itr_raise_pi(CFG_CORE_ASYNC_NOTIF_GIC_INTID); - - cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); -} bool notif_async_is_started(void) { diff --git a/core/kernel/notif_default.c b/core/kernel/notif_default.c new file mode 100644 index 0000000000000000000000000000000000000000..85b156867d660116dd39736966bb634502ff1dbd --- /dev/null +++ b/core/kernel/notif_default.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, Linaro Limited + */ + +#include <assert.h> +#include <bitstring.h> +#include <kernel/interrupt.h> +#include <kernel/notif.h> +#include <kernel/spinlock.h> +#include <trace.h> +#include <types_ext.h> + +static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); +static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); +static unsigned int notif_default_lock = SPINLOCK_UNLOCK; + +TEE_Result notif_alloc_async_value(uint32_t *val) +{ + static bool alloc_values_inited; + uint32_t old_itr_status = 0; + int bit = 0; + + assert(interrupt_can_raise_pi(interrupt_get_main_chip())); + + old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); + + if (!alloc_values_inited) { + bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); + alloc_values_inited = true; + } + + bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + if (bit >= 0) { + *val = bit; + bit_set(notif_alloc_values, bit); + } + + cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); + + if (bit < 0) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +void notif_free_async_value(uint32_t val) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); + + assert(val < NOTIF_ASYNC_VALUE_MAX); + assert(bit_test(notif_alloc_values, val)); + bit_clear(notif_alloc_values, val); + + cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); +} + +uint32_t notif_get_value(bool *value_valid, bool *value_pending) +{ + uint32_t old_itr_status = 0; + uint32_t res = 0; + int bit = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); + + bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + *value_valid = (bit >= 0); + if (!*value_valid) { + *value_pending = false; + goto out; + } + + res = bit; + bit_clear(notif_values, res); + bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + *value_pending = (bit >= 0); +out: + cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); + + return res; +} + +void notif_send_async(uint32_t value) +{ + uint32_t old_itr_status = 0; + struct itr_chip *itr_chip = interrupt_get_main_chip(); + + assert(value <= NOTIF_ASYNC_VALUE_MAX); + old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); + + DMSG("0x%"PRIx32, value); + bit_set(notif_values, value); + interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID); + + cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); +} diff --git a/core/kernel/panic.c b/core/kernel/panic.c index 18028fbfd3c7f47e8dfb5c45b3c80aca37693e95..9edef97d81b52cb76e179807f24d871c2a86e14d 100644 --- a/core/kernel/panic.c +++ b/core/kernel/panic.c @@ -4,11 +4,62 @@ * Copyright (c) 2014, STMicroelectronics International N.V. */ +#include <initcall.h> +#include <kernel/interrupt.h> +#include <kernel/misc.h> #include <kernel/panic.h> #include <kernel/thread.h> #include <kernel/unwind.h> #include <trace.h> +/* SGI number chosen to halt other cores must be in the secure SGI range */ +static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || + (CFG_HALT_CORES_ON_PANIC_SGI >= 8 && + CFG_HALT_CORES_ON_PANIC_SGI < 16)); + +static enum itr_return __noreturn +multi_core_panic_it_handler(struct itr_handler *hdl __unused) +{ + IMSG("Halting CPU %zu", get_core_pos()); + + while (true) + cpu_idle(); +} + +static struct itr_handler multi_core_panic_handler = { + .it = CFG_HALT_CORES_ON_PANIC_SGI, + .handler = multi_core_panic_it_handler, +}; +DECLARE_KEEP_PAGER(multi_core_panic_handler); + +static void notify_other_cores(void) +{ + struct itr_chip *chip = interrupt_get_main_chip_may_fail(); + + if (chip) + interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI, + ITR_CPU_MASK_TO_OTHER_CPUS); + else + EMSG("Can't notify other cores, main interrupt chip not set"); +} + +static TEE_Result init_multi_core_panic_handler(void) +{ + if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1) + return TEE_SUCCESS; + + if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &multi_core_panic_handler)) + panic(); + + interrupt_enable(interrupt_get_main_chip(), + multi_core_panic_handler.it); + + return TEE_SUCCESS; +} + +boot_final(init_multi_core_panic_handler); + void __do_panic(const char *file __maybe_unused, const int line __maybe_unused, const char *func __maybe_unused, @@ -17,8 +68,6 @@ void __do_panic(const char *file __maybe_unused, /* disable prehemption */ (void)thread_mask_exceptions(THREAD_EXCP_ALL); - /* TODO: notify other cores */ - /* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */ if (!file && !func && !msg) EMSG_RAW("Panic"); @@ -29,6 +78,10 @@ void __do_panic(const char *file __maybe_unused, func ? "<" : "", func ? func : "", func ? ">" : ""); print_kernel_stack(); + + if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1) + notify_other_cores(); + /* abort current execution */ while (1) cpu_idle(); diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk index 75d3368651425756755ab5bda7bcec12824a47db..3e81d5f8f124d914955d38e0d258cf71fac7a090 100644 --- a/core/kernel/sub.mk +++ b/core/kernel/sub.mk @@ -39,6 +39,7 @@ srcs-y += mutex.c srcs-$(CFG_LOCKDEP) += mutex_lockdep.c srcs-y += wait_queue.c srcs-y += notif.c +srcs-$(_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL) += notif_default.c srcs-y += thread.c ifeq ($(CFG_WITH_USER_TA),y) @@ -51,6 +52,8 @@ endif srcs-$(CFG_EMBEDDED_TS) += embedded_ts.c srcs-y += pseudo_ta.c +srcs-$(CFG_TRANSFER_LIST) += transfer_list.c + ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile spin_lock_debug.c file as it provides # common APIs that are needed for ftrace framework to trace syscalls. diff --git a/core/kernel/tee_ta_manager.c b/core/kernel/tee_ta_manager.c index 97dee430c30b247f91d7c0eec5e8b92e37ba6fcf..6117c3a01f5cb7105232653921975ee73afaa4f1 100644 --- a/core/kernel/tee_ta_manager.c +++ b/core/kernel/tee_ta_manager.c @@ -21,6 +21,7 @@ #include <mm/core_mmu.h> #include <mm/mobj.h> #include <mm/vm.h> +#include <pta_stats.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -37,12 +38,6 @@ #if defined(CFG_TA_STATS) #define MAX_DUMP_SESS_NUM (16) -struct tee_ta_dump_stats { - TEE_UUID uuid; - uint32_t panicked; /* True if TA has panicked */ - uint32_t sess_num; /* Number of opened session */ - struct malloc_stats heap; -}; struct tee_ta_dump_ctx { TEE_UUID uuid; @@ -740,7 +735,7 @@ TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, if (!res) *sess = s; else - EMSG("Failed. Return error 0x%x", res); + EMSG("Failed for TA %pUl. Return error %#"PRIx32, uuid, res); return res; } @@ -879,7 +874,7 @@ static void init_dump_ctx(struct tee_ta_dump_ctx *dump_ctx) } static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx, - struct tee_ta_dump_stats *dump_stats, + struct pta_stats_ta *dump_stats, size_t ta_count) { TEE_Result res = TEE_SUCCESS; @@ -892,7 +887,7 @@ static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx, nsec_sessions_list_head(&open_sessions); for (i = 0; i < ta_count; i++) { - struct tee_ta_dump_stats *stats = &dump_stats[i]; + struct pta_stats_ta *stats = &dump_stats[i]; memcpy(&stats->uuid, &dump_ctx[i].uuid, sizeof(dump_ctx[i].uuid)); @@ -932,7 +927,7 @@ static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx, TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size) { TEE_Result res = TEE_SUCCESS; - struct tee_ta_dump_stats *dump_stats = NULL; + struct pta_stats_ta *dump_stats = NULL; struct tee_ta_dump_ctx *dump_ctx = NULL; struct tee_ta_ctx *ctx = NULL; size_t sz = 0; @@ -948,7 +943,7 @@ TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size) if (is_user_ta_ctx(&ctx->ts_ctx)) ta_count++; - sz = sizeof(struct tee_ta_dump_stats) * ta_count; + sz = sizeof(struct pta_stats_ta) * ta_count; if (!sz) { /* sz = 0 means there is no UTA, return no item found. */ res = TEE_ERROR_ITEM_NOT_FOUND; @@ -964,7 +959,7 @@ TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size) DMSG("Data alignment"); res = TEE_ERROR_BAD_PARAMETERS; } else { - dump_stats = (struct tee_ta_dump_stats *)buf; + dump_stats = (struct pta_stats_ta *)buf; dump_ctx = malloc(sizeof(struct tee_ta_dump_ctx) * ta_count); if (!dump_ctx) res = TEE_ERROR_OUT_OF_MEMORY; diff --git a/core/kernel/tpm.c b/core/kernel/tpm.c index 4091a3ed60abc7cc24ec5179777042162efb9f5b..f9abf267e9e8d987452e939ec56b710eb8a34054 100644 --- a/core/kernel/tpm.c +++ b/core/kernel/tpm.c @@ -51,7 +51,7 @@ static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf, err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr, sizeof(uint32_t) * 2); if (err < 0) { - EMSG("Error setting property DTB to zero\n"); + EMSG("Error setting property DTB to zero"); return err; } } diff --git a/core/kernel/trace_ext.c b/core/kernel/trace_ext.c index 6ed3bf94cce4f7995fc5989bf83699ac9d1e770b..007d6c30500ad1ab7cb90b946a833fc9a883ab6a 100644 --- a/core/kernel/trace_ext.c +++ b/core/kernel/trace_ext.c @@ -8,6 +8,7 @@ #include <kernel/misc.h> #include <kernel/spinlock.h> #include <kernel/thread.h> +#include <kernel/virtualization.h> #include <mm/core_mmu.h> const char trace_ext_prefix[] = "TC"; @@ -61,3 +62,8 @@ int trace_ext_get_core_id(void) else return -1; } + +int trace_ext_get_guest_id(void) +{ + return virt_get_current_guest_id(); +} diff --git a/core/kernel/transfer_list.c b/core/kernel/transfer_list.c new file mode 100644 index 0000000000000000000000000000000000000000..1be1b849cf91dd68782536f3b868e5fe71092598 --- /dev/null +++ b/core/kernel/transfer_list.c @@ -0,0 +1,591 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Linaro Limited + */ + +/******************************************************************************* + * Transfer list library compliant with the Firmware Handoff specification at: + * https://github.com/FirmwareHandoff/firmware_handoff + ******************************************************************************/ + +#include <kernel/cache_helpers.h> +#include <kernel/panic.h> +#include <kernel/transfer_list.h> +#include <mm/core_memprot.h> +#include <mm/core_mmu.h> +#include <string.h> +#include <util.h> + +/******************************************************************************* + * Adapt a physical address to match the maximum transfer entry data alignment + * required by an existing transfer list. + * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). + * @pa: Physical address for adapting. + * @tl: Pointer to the existing transfer list. + * Return the adapted physical address. + ******************************************************************************/ +static paddr_t get_align_base_addr(paddr_t pa, + struct transfer_list_header *tl) +{ + paddr_t align_mask = TL_ALIGNMENT_FROM_ORDER(tl->alignment) - 1; + paddr_t align_off = (paddr_t)tl & align_mask; + paddr_t new_addr = (pa & ~align_mask) + align_off; + + if (new_addr < pa) + new_addr += TL_ALIGNMENT_FROM_ORDER(tl->alignment); + + return new_addr; +} + +static void unmap_list(struct transfer_list_header *tl, size_t sz) +{ + if (core_mmu_remove_mapping(MEM_AREA_TRANSFER_LIST, tl, sz)) + panic("Failed to remove transfer list mapping"); +} + +struct transfer_list_header *transfer_list_map(paddr_t pa) +{ + struct transfer_list_header *tl = NULL; + size_t sz = SMALL_PAGE_SIZE; + size_t old_sz = 0; + + while (true) { + tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, sz); + if (!tl) { + EMSG("Failed to map TL with PA %#"PRIxPA", size %#zx", + pa, sz); + return NULL; + } + old_sz = sz; + + if (transfer_list_check_header(tl) == TL_OPS_NONE) { + unmap_list(tl, sz); + return NULL; + } + + if (tl->max_size <= sz) + return tl; + + sz = ROUNDUP(tl->max_size, SMALL_PAGE_SIZE); + unmap_list(tl, old_sz); + } +} + +void transfer_list_unmap_sync(struct transfer_list_header *tl) +{ + size_t sz = tl->max_size; + + transfer_list_update_checksum(tl); + dcache_cleaninv_range(tl, sz); + unmap_list(tl, sz); +} + +void transfer_list_unmap_nosync(struct transfer_list_header *tl) +{ + unmap_list(tl, tl->max_size); +} + +void transfer_list_dump(struct transfer_list_header *tl) +{ + struct transfer_list_entry *tl_e = NULL; + int i __maybe_unused = 0; + + if (!tl) + return; + + DMSG("Dump transfer list:"); + DMSG("signature %#"PRIx32, tl->signature); + DMSG("checksum %#"PRIx8, tl->checksum); + DMSG("version %#"PRIx8, tl->version); + DMSG("hdr_size %#"PRIx8, tl->hdr_size); + DMSG("alignment %#"PRIx8, tl->alignment); + DMSG("size %#"PRIx32, tl->size); + DMSG("max_size %#"PRIx32, tl->max_size); + DMSG("flags %#"PRIx32, tl->flags); + while (true) { + tl_e = transfer_list_next(tl, tl_e); + if (!tl_e) + break; + + DMSG("Entry %d:", i++); + DMSG("tag_id %#"PRIx16, tl_e->tag_id); + DMSG("hdr_size %#"PRIx8, tl_e->hdr_size); + DMSG("data_size %#"PRIx32, tl_e->data_size); + DMSG("data_addr %#"PRIxVA, + (vaddr_t)transfer_list_entry_data(tl_e)); + } +} + +/******************************************************************************* + * Creating a transfer list in a specified reserved memory region. + * Compliant with 2.4.5 of Firmware Handoff specification (v0.9). + * @pa: Physical address for residing the new transfer list. + * @max_size: Maximum size of the new transfer list. + * Return pointer to the created transfer list or NULL on error. + ******************************************************************************/ +struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size) +{ + struct transfer_list_header *tl = NULL; + int align = TL_ALIGNMENT_FROM_ORDER(TRANSFER_LIST_INIT_MAX_ALIGN); + + if (!pa || !max_size) + return NULL; + + if (!IS_ALIGNED(pa, align) || !IS_ALIGNED(max_size, align) || + max_size < sizeof(*tl)) + return NULL; + + tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, max_size); + if (!tl) + return NULL; + + memset(tl, 0, max_size); + tl->signature = TRANSFER_LIST_SIGNATURE; + tl->version = TRANSFER_LIST_VERSION; + tl->hdr_size = sizeof(*tl); + tl->alignment = TRANSFER_LIST_INIT_MAX_ALIGN; /* initial max align */ + tl->size = sizeof(*tl); /* initial size is the size of header */ + tl->max_size = max_size; + tl->flags = TL_FLAGS_HAS_CHECKSUM; + + transfer_list_update_checksum(tl); + + return tl; +} + +/******************************************************************************* + * Relocating a transfer list to a specified reserved memory region. + * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list for relocating. + * @pa: Physical address for relocating the transfer list. + * @max_size: Maximum size of the transfer list after relocating + * Return pointer to the relocated transfer list or NULL on error. + ******************************************************************************/ +struct transfer_list_header * +transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, + size_t max_size) +{ + paddr_t new_addr = 0; + struct transfer_list_header *new_tl = NULL; + size_t new_max_size = 0; + + if (!tl || !pa || !max_size) + return NULL; + + new_addr = get_align_base_addr(pa, tl); + new_max_size = max_size - (new_addr - pa); + + /* The new space is not sufficient for the TL */ + if (tl->size > new_max_size) + return NULL; + + new_tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, new_addr, + new_max_size); + if (!new_tl) + return NULL; + + memmove(new_tl, tl, tl->size); + new_tl->max_size = new_max_size; + + transfer_list_update_checksum(new_tl); + transfer_list_unmap_nosync(tl); + + return new_tl; +} + +/******************************************************************************* + * Verifying the header of a transfer list. + * Compliant with 2.4.1 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * Return transfer list operation status code. + ******************************************************************************/ +int transfer_list_check_header(const struct transfer_list_header *tl) +{ + if (!tl) + return TL_OPS_NONE; + + if (tl->signature != TRANSFER_LIST_SIGNATURE) { + EMSG("Bad transfer list signature %#"PRIx32, tl->signature); + return TL_OPS_NONE; + } + + if (!tl->max_size) { + EMSG("Bad transfer list max size %#"PRIx32, tl->max_size); + return TL_OPS_NONE; + } + + if (tl->size > tl->max_size) { + EMSG("Bad transfer list size %#"PRIx32, tl->size); + return TL_OPS_NONE; + } + + if (tl->hdr_size != sizeof(struct transfer_list_header)) { + EMSG("Bad transfer list header size %#"PRIx8, tl->hdr_size); + return TL_OPS_NONE; + } + + if (!transfer_list_verify_checksum(tl)) { + EMSG("Bad transfer list checksum %#"PRIx8, tl->checksum); + return TL_OPS_NONE; + } + + if (tl->version == 0) { + EMSG("Transfer list version is invalid"); + return TL_OPS_NONE; + } else if (tl->version == TRANSFER_LIST_VERSION) { + DMSG("Transfer list version is valid for all operations"); + return TL_OPS_ALL; + } else if (tl->version > TRANSFER_LIST_VERSION) { + DMSG("Transfer list version is valid for read-only"); + return TL_OPS_RO; + } + + DMSG("Old transfer list version is detected"); + return TL_OPS_CUS; +} + +/******************************************************************************* + * Enumerate the next transfer entry. + * @tl: Pointer to the transfer list. + * @cur: Pointer to the current transfer entry where we want to search for the + * next one. + * Return pointer to the next transfer entry or NULL on error or if @cur is the + * last entry. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl, + struct transfer_list_entry *cur) +{ + struct transfer_list_entry *tl_e = NULL; + vaddr_t tl_ev = 0; + vaddr_t va = 0; + vaddr_t ev = 0; + size_t sz = 0; + + if (!tl) + return NULL; + + tl_ev = (vaddr_t)tl + tl->size; + + if (cur) { + va = (vaddr_t)cur; + /* check if the total size overflow */ + if (ADD_OVERFLOW(cur->hdr_size, cur->data_size, &sz)) + return NULL; + /* roundup to the next entry */ + if (ADD_OVERFLOW(va, sz, &va) || + ROUNDUP_OVERFLOW(va, TRANSFER_LIST_GRANULE, &va)) + return NULL; + } else { + va = (vaddr_t)tl + tl->hdr_size; + } + + tl_e = (struct transfer_list_entry *)va; + + if (va + sizeof(*tl_e) > tl_ev || tl_e->hdr_size < sizeof(*tl_e) || + ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || + ADD_OVERFLOW(va, sz, &ev) || ev > tl_ev) + return NULL; + + return tl_e; +} + +/******************************************************************************* + * Calculate the byte sum (modulo 256) of a transfer list. + * @tl: Pointer to the transfer list. + * Return byte sum of the transfer list. + ******************************************************************************/ +static uint8_t calc_byte_sum(const struct transfer_list_header *tl) +{ + uint8_t *b = (uint8_t *)tl; + uint8_t cs = 0; + size_t n = 0; + + for (n = 0; n < tl->size; n++) + cs += b[n]; + + return cs; +} + +/******************************************************************************* + * Update the checksum of a transfer list. + * @tl: Pointer to the transfer list. + * Return updated checksum of the transfer list. + ******************************************************************************/ +void transfer_list_update_checksum(struct transfer_list_header *tl) +{ + uint8_t cs = 0; + + if (!tl || !(tl->flags & TL_FLAGS_HAS_CHECKSUM)) + return; + + cs = calc_byte_sum(tl); + cs -= tl->checksum; + cs = 256 - cs; + tl->checksum = cs; + assert(transfer_list_verify_checksum(tl)); +} + +/******************************************************************************* + * Verify the checksum of a transfer list. + * @tl: Pointer to the transfer list. + * Return true if verified or false if not. + ******************************************************************************/ +bool transfer_list_verify_checksum(const struct transfer_list_header *tl) +{ + if (!tl) + return false; + + if (!(tl->flags & TL_FLAGS_HAS_CHECKSUM)) + return true; + + return !calc_byte_sum(tl); +} + +/******************************************************************************* + * Update the data size of a transfer entry. + * @tl: Pointer to the transfer list. + * @tl_e: Pointer to the transfer entry. + * @new_data_size: New data size of the transfer entry. + * Return true on success or false on error. + ******************************************************************************/ +bool transfer_list_set_data_size(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e, + uint32_t new_data_size) +{ + vaddr_t tl_old_ev = 0; + vaddr_t new_ev = 0; + vaddr_t old_ev = 0; + vaddr_t r_new_ev = 0; + struct transfer_list_entry *dummy_te = NULL; + size_t gap = 0; + size_t mov_dis = 0; + size_t sz = 0; + + if (!tl || !tl_e) + return false; + + tl_old_ev = (vaddr_t)tl + tl->size; + + /* + * Calculate the old and new end of transfer entry + * both must be roundup to align with TRANSFER_LIST_GRANULE + */ + if (ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || + ADD_OVERFLOW((vaddr_t)tl_e, sz, &old_ev) || + ROUNDUP_OVERFLOW(old_ev, TRANSFER_LIST_GRANULE, &old_ev)) + return false; + + if (ADD_OVERFLOW(tl_e->hdr_size, new_data_size, &sz) || + ADD_OVERFLOW((vaddr_t)tl_e, sz, &new_ev) || + ROUNDUP_OVERFLOW(new_ev, TRANSFER_LIST_GRANULE, &new_ev)) + return false; + + if (new_ev > old_ev) { + /* + * Move distance should be rounded up to match the entry data + * alignment. + * Ensure that the increased size doesn't exceed the max size + * of TL + */ + mov_dis = new_ev - old_ev; + if (ROUNDUP_OVERFLOW(mov_dis, + TL_ALIGNMENT_FROM_ORDER(tl->alignment), + &mov_dis) || + tl->size + mov_dis > tl->max_size) { + return false; + } + r_new_ev = old_ev + mov_dis; + tl->size += mov_dis; + } else { + /* + * Move distance should be rounded down to match the entry data + * alignment. + */ + mov_dis = ROUNDDOWN(old_ev - new_ev, + TL_ALIGNMENT_FROM_ORDER(tl->alignment)); + r_new_ev = old_ev - mov_dis; + tl->size -= mov_dis; + } + /* Move all following entries to fit in the expanded or shrunk space */ + memmove((void *)r_new_ev, (void *)old_ev, tl_old_ev - old_ev); + + /* + * Fill the gap due to round up/down with a void entry if the size of + * the gap is more than an entry header. + */ + gap = r_new_ev - new_ev; + if (gap >= sizeof(*dummy_te)) { + /* Create a dummy transfer entry to fill up the gap */ + dummy_te = (struct transfer_list_entry *)new_ev; + dummy_te->tag_id = TL_TAG_EMPTY; + dummy_te->reserved0 = 0; + dummy_te->hdr_size = sizeof(*dummy_te); + dummy_te->data_size = gap - sizeof(*dummy_te); + } + + tl_e->data_size = new_data_size; + + transfer_list_update_checksum(tl); + return true; +} + +/******************************************************************************* + * Remove a specified transfer entry from a transfer list. + * @tl: Pointer to the transfer list. + * @tl_e: Pointer to the transfer entry. + * Return true on success or false on error. + ******************************************************************************/ +bool transfer_list_rem(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e) +{ + if (!tl || !tl_e || (vaddr_t)tl_e > (vaddr_t)tl + tl->size) + return false; + + tl_e->tag_id = TL_TAG_EMPTY; + tl_e->reserved0 = 0; + transfer_list_update_checksum(tl); + return true; +} + +/******************************************************************************* + * Add a new transfer entry into a transfer list. + * Compliant with 2.4.3 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID for the new transfer entry. + * @data_size: Data size of the new transfer entry. + * @data: Pointer to the data for the new transfer entry. + * NULL to skip data copying. + * Return pointer to the added transfer entry or NULL on error. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, + uint16_t tag_id, + uint32_t data_size, + const void *data) +{ + vaddr_t max_tl_ev = 0; + vaddr_t tl_ev = 0; + vaddr_t ev = 0; + struct transfer_list_entry *tl_e = NULL; + size_t sz = 0; + + if (!tl) + return NULL; + + max_tl_ev = (vaddr_t)tl + tl->max_size; + tl_ev = (vaddr_t)tl + tl->size; + ev = tl_ev; + + /* + * Skip the step 1 (optional step). + * New transfer entry will be added into the tail + */ + if (ADD_OVERFLOW(sizeof(*tl_e), data_size, &sz) || + ADD_OVERFLOW(ev, sz, &ev) || + ROUNDUP_OVERFLOW(ev, TRANSFER_LIST_GRANULE, &ev) || + ev > max_tl_ev) { + return NULL; + } + + tl_e = (struct transfer_list_entry *)tl_ev; + *tl_e = (struct transfer_list_entry){ + .tag_id = tag_id, + .hdr_size = sizeof(*tl_e), + .data_size = data_size, + }; + + tl->size += ev - tl_ev; + + if (data) + memmove(tl_e + tl_e->hdr_size, data, data_size); + + transfer_list_update_checksum(tl); + + return tl_e; +} + +/******************************************************************************* + * Add a new transfer entry into a transfer list with specified new data + * alignment requirement. + * Compliant with 2.4.4 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID for the new transfer entry. + * @data_size: Data size of the new transfer entry. + * @data: Pointer to the data for the new transfer entry. + * @alignment: New data alignment specified as a power of two. + * Return pointer to the added transfer entry or NULL on error. + ******************************************************************************/ +struct transfer_list_entry * +transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, + uint32_t data_size, const void *data, + uint8_t alignment) +{ + struct transfer_list_entry *tl_e = NULL; + vaddr_t tl_ev = 0; + vaddr_t ev = 0; + vaddr_t new_tl_ev = 0; + size_t dummy_te_data_sz = 0; + + if (!tl) + return NULL; + + tl_ev = (vaddr_t)tl + tl->size; + ev = tl_ev + sizeof(struct transfer_list_entry); + + if (!IS_ALIGNED(ev, TL_ALIGNMENT_FROM_ORDER(alignment))) { + /* + * Transfer entry data address is not aligned to the new + * alignment. Fill the gap with an empty transfer entry as a + * placeholder before adding the desired transfer entry + */ + new_tl_ev = ROUNDUP(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) - + sizeof(struct transfer_list_entry); + assert(new_tl_ev - tl_ev > sizeof(struct transfer_list_entry)); + dummy_te_data_sz = new_tl_ev - tl_ev - + sizeof(struct transfer_list_entry); + if (!transfer_list_add(tl, TL_TAG_EMPTY, dummy_te_data_sz, + NULL)) { + return NULL; + } + } + + tl_e = transfer_list_add(tl, tag_id, data_size, data); + + if (alignment > tl->alignment) { + tl->alignment = alignment; + transfer_list_update_checksum(tl); + } + + return tl_e; +} + +/******************************************************************************* + * Search for an existing transfer entry with the specified tag id from a + * transfer list. + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID to match a transfer entry. + * Return pointer to the found transfer entry or NULL if not found. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, + uint16_t tag_id) +{ + struct transfer_list_entry *tl_e = NULL; + + do { + tl_e = transfer_list_next(tl, tl_e); + } while (tl_e && tl_e->tag_id != tag_id); + + return tl_e; +} + +/******************************************************************************* + * Retrieve the data pointer of a specified transfer entry. + * @tl_e: Pointer to the transfer entry. + * Return pointer to the transfer entry data or NULL on error. + ******************************************************************************/ +void *transfer_list_entry_data(struct transfer_list_entry *tl_e) +{ + if (!tl_e) + return NULL; + + return (uint8_t *)tl_e + tl_e->hdr_size; +} diff --git a/core/kernel/user_access.c b/core/kernel/user_access.c index 22b48fbb6b0259baa880139cb4899f45d810ba82..3f229f985713741530a3ac6309f1ca749c9b4bb1 100644 --- a/core/kernel/user_access.c +++ b/core/kernel/user_access.c @@ -310,7 +310,7 @@ uint32_t kaddr_to_uref(void *kaddr) uref -= VCORE_START_VA; assert(uref < (UINT32_MAX >> MEMTAG_TAG_WIDTH)); - uref |= memtag_get_tag(kaddr) << uref_tag_shift; + uref |= (vaddr_t)memtag_get_tag(kaddr) << uref_tag_shift; return uref; } diff --git a/core/mm/core_mmu.c b/core/mm/core_mmu.c index 584ff78e0d607aa813d05201d89e914b872e294d..c894e3fc2fa81df0dd6ffde42b26be1f63c8b024 100644 --- a/core/mm/core_mmu.c +++ b/core/mm/core_mmu.c @@ -471,6 +471,7 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start, break; case MEM_AREA_EXT_DT: case MEM_AREA_MANIFEST_DT: + case MEM_AREA_RAM_NSEC: case MEM_AREA_RES_VASPACE: case MEM_AREA_SHM_VASPACE: case MEM_AREA_TS_VASPACE: @@ -596,7 +597,6 @@ static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused) /* Check special memories comply with registered memories */ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, - size_t len, const struct core_mmu_phys_mem *start, const struct core_mmu_phys_mem *end, const char *area_name __maybe_unused) @@ -604,7 +604,6 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, const struct core_mmu_phys_mem *mem; const struct core_mmu_phys_mem *mem2; struct tee_mmap_region *mmap; - size_t n; if (start == end) { DMSG("No %s memory area defined", area_name); @@ -632,7 +631,7 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, * This is called before reserved VA space is loaded in mem_map. */ for (mem = start; mem < end; mem++) { - for (mmap = mem_map, n = 0; n < len; mmap++, n++) { + for (mmap = mem_map; mmap->type != MEM_AREA_END; mmap++) { if (core_is_buffer_intersect(mem->addr, mem->size, mmap->pa, mmap->size)) { MSG_MEM_INSTERSECT(mem->addr, mem->size, @@ -759,6 +758,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) return attr | TEE_MATTR_PRW | cached; case MEM_AREA_MANIFEST_DT: return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; + case MEM_AREA_TRANSFER_LIST: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; case MEM_AREA_EXT_DT: /* * If CFG_MAP_EXT_DT_SECURE is enabled map the external device @@ -778,6 +779,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) case MEM_AREA_RAM_SEC: case MEM_AREA_SEC_RAM_OVERALL: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; + case MEM_AREA_ROM_SEC: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; case MEM_AREA_RES_VASPACE: case MEM_AREA_SHM_VASPACE: return 0; @@ -1075,8 +1078,7 @@ static size_t collect_mem_ranges(struct tee_mmap_region *memory_map, } if (IS_ENABLED(CFG_SECURE_DATA_PATH)) - verify_special_mem_areas(memory_map, num_elems, - phys_sdp_mem_begin, + verify_special_mem_areas(memory_map, phys_sdp_mem_begin, phys_sdp_mem_end, "SDP"); add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE, @@ -1434,6 +1436,7 @@ static void check_mem_map(struct tee_mmap_region *map) case MEM_AREA_IO_NSEC: case MEM_AREA_EXT_DT: case MEM_AREA_MANIFEST_DT: + case MEM_AREA_TRANSFER_LIST: case MEM_AREA_RAM_SEC: case MEM_AREA_RAM_NSEC: case MEM_AREA_RES_VASPACE: diff --git a/core/mm/tee_mm.c b/core/mm/tee_mm.c index c61306d757f93de9d13a3d3ddaa4fb5b900a6a1d..95084ca1e448756d8f60670a0d4415fb86a6f2e3 100644 --- a/core/mm/tee_mm.c +++ b/core/mm/tee_mm.c @@ -8,6 +8,7 @@ #include <kernel/tee_common.h> #include <mm/tee_mm.h> #include <mm/tee_pager.h> +#include <pta_stats.h> #include <trace.h> #include <util.h> @@ -104,7 +105,7 @@ static size_t tee_mm_stats_allocated(tee_mm_pool_t *pool) return sz << pool->shift; } -void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats, +void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats, bool reset) { uint32_t exceptions; diff --git a/core/pta/attestation.c b/core/pta/attestation.c index ab5a3bcc14547d9344bae67debc0f33f984e9880..d8a41075875c73e9f111b8183b4d3d4d2dc3a915 100644 --- a/core/pta/attestation.c +++ b/core/pta/attestation.c @@ -228,8 +228,8 @@ static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id, if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; - res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops, - &po); + res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, + TEE_POBJ_USAGE_OPEN, fops, &po); if (res) return res; @@ -272,8 +272,8 @@ static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id, if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; - res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, - fops, &po); + res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, + TEE_POBJ_USAGE_OPEN, fops, &po); if (res) return res; diff --git a/core/pta/bcm/gpio.c b/core/pta/bcm/gpio.c index 43ed935d60d11ab039f27ebac9a2c9282790e11f..f77f9230c8252879dc94dbec22ee8737d9c22550 100644 --- a/core/pta/bcm/gpio.c +++ b/core/pta/bcm/gpio.c @@ -181,7 +181,7 @@ static TEE_Result invoke_command(void *session_context __unused, res = pta_gpio_get(param_types, params); break; default: - EMSG("cmd: %d Not supported %s\n", cmd_id, GPIO_TA_NAME); + EMSG("cmd: %d Not supported %s", cmd_id, GPIO_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } diff --git a/core/pta/stats.c b/core/pta/stats.c index 933d8e104b54197d85376c6979ac82d8e75c11be..966592f008af6fba00c09845a4c97fb41846de30 100644 --- a/core/pta/stats.c +++ b/core/pta/stats.c @@ -3,67 +3,33 @@ * Copyright (c) 2015, Linaro Limited */ #include <compiler.h> +#include <drivers/clk.h> +#include <drivers/regulator.h> #include <kernel/pseudo_ta.h> #include <kernel/tee_time.h> #include <malloc.h> #include <mm/tee_mm.h> #include <mm/tee_pager.h> +#include <pta_stats.h> #include <stdio.h> #include <string.h> #include <string_ext.h> +#include <tee_api_types.h> #include <trace.h> -#define TA_NAME "stats.ta" - -#define STATS_UUID \ - { 0xd96a5b40, 0xe2c7, 0xb1af, \ - { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } - -#define STATS_CMD_PAGER_STATS 0 -#define STATS_CMD_ALLOC_STATS 1 -#define STATS_CMD_MEMLEAK_STATS 2 -/* - * UTEE_ENTRY_FUNC_DUMP_MEMSTATS - * [out] memref[0] Array of context information of loaded TAs - * - * Each cell of the TA information array contains: - * TEE_UUID TA UUID - * uint32_t Non zero if TA panicked, 0 otherwise - * uint32_t Number of sessions opened by the TA - * uint32_t Byte size currently allocated in TA heap - * uint32_t Max bytes allocated since last stats reset - * uint32_t TA heap pool byte size - * uint32_t Number of failed allocation requests - * uint32_t Biggest byte size which allocation failed - * uint32_t Biggest byte size which allocation succeeded - */ -#define STATS_CMD_TA_STATS 3 - -/* - * STATS_CMD_GET_TIME - Get both REE time and TEE time - * - * [out] value[0].a REE time as seen by OP-TEE in seconds - * [out] value[0].b REE time as seen by OP-TEE, milliseconds part - * [out] value[1].a TEE system time in seconds - * [out] value[1].b TEE system time, milliseconds part - */ -#define STATS_CMD_GET_TIME 4 - -#define STATS_NB_POOLS 4 - static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { - struct malloc_stats *stats; - uint32_t size_to_retrieve; - uint32_t pool_id; - uint32_t i; + struct pta_stats_alloc *stats = NULL; + uint32_t size_to_retrieve = 0; + uint32_t pool_id = 0; + uint32_t i = 0; /* * p[0].value.a = pool id (from 0 to n) * - 0 means all the pools to be retrieved * - 1..n means pool id * p[0].value.b = 0 if no reset of the stats - * p[1].memref.buffer = output buffer to struct malloc_stats + * p[1].memref.buffer = output buffer to struct pta_stats_alloc */ if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, @@ -76,8 +42,8 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) if (pool_id > STATS_NB_POOLS) return TEE_ERROR_BAD_PARAMETERS; - size_to_retrieve = sizeof(struct malloc_stats); - if (!pool_id) + size_to_retrieve = sizeof(struct pta_stats_alloc); + if (pool_id == ALLOC_ID_ALL) size_to_retrieve *= STATS_NB_POOLS; if (p[1].memref.size < size_to_retrieve) { @@ -87,30 +53,30 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) p[1].memref.size = size_to_retrieve; stats = p[1].memref.buffer; - for (i = 1; i <= STATS_NB_POOLS; i++) { - if ((pool_id) && (i != pool_id)) + for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) { + if (pool_id != ALLOC_ID_ALL && i != pool_id) continue; switch (i) { - case 1: + case ALLOC_ID_HEAP: malloc_get_stats(stats); strlcpy(stats->desc, "Heap", sizeof(stats->desc)); if (p[0].value.b) malloc_reset_stats(); break; - case 2: + case ALLOC_ID_PUBLIC_DDR: EMSG("public DDR not managed by secure side anymore"); break; - case 3: + case ALLOC_ID_TA_RAM: tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats, !!p[0].value.b); strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc)); break; #ifdef CFG_NS_VIRTUALIZATION - case 4: + case ALLOC_ID_NEXUS_HEAP: nex_malloc_get_stats(stats); strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); if (p[0].value.b) @@ -130,7 +96,7 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { - struct tee_pager_stats stats; + struct tee_pager_stats stats = { }; if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, @@ -189,6 +155,7 @@ static TEE_Result get_user_ta_stats(uint32_t type, static TEE_Result get_system_time(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { + TEE_Result ret = TEE_ERROR_GENERIC; TEE_Time ree_time = { }; TEE_Time tee_time = { }; @@ -198,8 +165,13 @@ static TEE_Result get_system_time(uint32_t type, TEE_PARAM_TYPE_NONE) != type) return TEE_ERROR_BAD_PARAMETERS; - tee_time_get_sys_time(&tee_time); - tee_time_get_ree_time(&ree_time); + ret = tee_time_get_sys_time(&tee_time); + if (ret) + return ret; + + ret = tee_time_get_ree_time(&ree_time); + if (ret) + return ret; p[0].value.a = ree_time.seconds; p[0].value.b = ree_time.millis; @@ -209,6 +181,28 @@ static TEE_Result get_system_time(uint32_t type, return TEE_SUCCESS; } +static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE) != type) + return TEE_ERROR_BAD_PARAMETERS; + + switch (p[0].value.a) { + case STATS_DRIVER_TYPE_CLOCK: + clk_print_tree(); + break; + case STATS_DRIVER_TYPE_REGULATOR: + regulator_print_tree(); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + /* * Trusted Application Entry Points */ @@ -228,12 +222,14 @@ static TEE_Result invoke_command(void *psess __unused, return get_user_ta_stats(ptypes, params); case STATS_CMD_GET_TIME: return get_system_time(ptypes, params); + case STATS_CMD_PRINT_DRIVER_INFO: + return print_driver_info(ptypes, params); default: break; } return TEE_ERROR_BAD_PARAMETERS; } -pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME, +pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); diff --git a/core/pta/stm32mp/remoteproc_pta.c b/core/pta/stm32mp/remoteproc_pta.c new file mode 100644 index 0000000000000000000000000000000000000000..b2eed7f257f8dc123f0cefc5b10f17f43f0f5ad3 --- /dev/null +++ b/core/pta/stm32mp/remoteproc_pta.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#include <crypto/crypto.h> +#include <drivers/clk.h> +#include <drivers/rstctrl.h> +#include <drivers/stm32_remoteproc.h> +#include <drivers/stm32mp_dt_bindings.h> +#include <drivers/stm32mp1_rcc.h> +#include <initcall.h> +#include <kernel/pseudo_ta.h> +#include <kernel/user_ta.h> +#include <remoteproc_pta.h> +#include <string.h> + +#include "rproc_pub_key.h" + +#define PTA_NAME "remoteproc.pta" + +/* + * UUID of the remoteproc Trusted application authorized to communicate with + * the remoteproc pseudo TA. The UID should match the one defined in the + * ta_remoteproc.h header file. + */ +#define TA_REMOTEPROC_UUID \ + { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* + * Firmware states + * REMOTEPROC_OFF: firmware is off + * REMOTEPROC_ON: firmware is running + */ +enum rproc_load_state { + REMOTEPROC_OFF = 0, + REMOTEPROC_ON, +}; + +/* Currently supporting a single remote processor instance */ +static enum rproc_load_state rproc_ta_state = REMOTEPROC_OFF; + +static TEE_Result rproc_pta_capabilities(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + /* Support only ELF format */ + params[1].value.a = PTA_RPROC_HWCAP_FMT_ELF; + + /* + * Due to stm32mp1 pager, secure memory is too expensive. Support hash + * protected image only, so that firmware image can be loaded from + * non-secure memory. + */ + params[2].value.a = PTA_RPROC_HWCAP_PROT_HASH_TABLE; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_load_segment(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + void *dst = NULL; + uint8_t *src = params[1].memref.buffer; + size_t size = params[1].memref.size; + uint8_t *hash = params[3].memref.buffer; + paddr_t da = (paddr_t)reg_pair_to_64(params[2].value.b, + params[2].value.a); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!hash || params[3].memref.size != TEE_SHA256_HASH_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in local context mapping */ + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + if (stm32_rproc_map(params[0].value.a, pa, size, &dst)) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + /* Copy the segment to the remote processor memory */ + memcpy(dst, src, size); + + /* Verify that loaded segment is valid */ + res = hash_sha256_check(hash, dst, size); + if (res) + memset(dst, 0, size); + + stm32_rproc_unmap(params[0].value.a, dst, size); + + return res; +} + +static TEE_Result rproc_pta_set_memory(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + void *dst = NULL; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + uint8_t value = params[3].value.a && 0xFF; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in CPU mapping */ + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + res = stm32_rproc_map(params[0].value.a, pa, size, &dst); + if (res) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + memset(dst, value, size); + + return stm32_rproc_unmap(params[0].value.a, dst, size); +} + +static TEE_Result rproc_pta_da_to_pa(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + paddr_t pa = 0; + + DMSG("Conversion for address %#"PRIxPA" size %zu", da, size); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Target address is expected 32bit, ensure 32bit MSB are zero */ + if (params[1].value.b || params[2].value.b) + return TEE_ERROR_BAD_PARAMETERS; + + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + reg_pair_from_64((uint64_t)pa, ¶ms[3].value.b, ¶ms[3].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_start(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + res = stm32_rproc_start(params[0].value.a); + if (res) + return res; + + rproc_ta_state = REMOTEPROC_ON; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_stop(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_ON) + return TEE_ERROR_BAD_STATE; + + res = stm32_rproc_stop(params[0].value.a); + if (res) + return res; + + rproc_ta_state = REMOTEPROC_OFF; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_verify_rsa_signature(TEE_Param *hash, + TEE_Param *sig, uint32_t algo) +{ + struct rsa_public_key key = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(rproc_pub_key_exponent); + size_t hash_size = (size_t)hash->memref.size; + size_t sig_size = (size_t)sig->memref.size; + + res = crypto_acipher_alloc_rsa_public_key(&key, sig_size); + if (res) + return res; + + res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res) + goto out; + + res = crypto_bignum_bin2bn(rproc_pub_key_modulus, + rproc_pub_key_modulus_size, key.n); + if (res) + goto out; + + res = crypto_acipher_rsassa_verify(algo, &key, hash_size, + hash->memref.buffer, hash_size, + sig->memref.buffer, sig_size); + +out: + crypto_acipher_free_rsa_public_key(&key); + + return res; +} + +static TEE_Result rproc_pta_verify_digest(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct rproc_pta_key_info *keyinfo = NULL; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + keyinfo = params[1].memref.buffer; + + if (!keyinfo || + rproc_pta_keyinfo_size(keyinfo) != params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + if (keyinfo->algo != TEE_ALG_RSASSA_PKCS1_V1_5_SHA256) + return TEE_ERROR_NOT_SUPPORTED; + + return rproc_pta_verify_rsa_signature(¶ms[2], ¶ms[3], + keyinfo->algo); +} + +static TEE_Result rproc_pta_invoke_command(void *session __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_RPROC_HW_CAPABILITIES: + return rproc_pta_capabilities(param_types, params); + case PTA_RPROC_LOAD_SEGMENT_SHA256: + return rproc_pta_load_segment(param_types, params); + case PTA_RPROC_SET_MEMORY: + return rproc_pta_set_memory(param_types, params); + case PTA_RPROC_FIRMWARE_START: + return rproc_pta_start(param_types, params); + case PTA_RPROC_FIRMWARE_STOP: + return rproc_pta_stop(param_types, params); + case PTA_RPROC_FIRMWARE_DA_TO_PA: + return rproc_pta_da_to_pa(param_types, params); + case PTA_RPROC_VERIFY_DIGEST: + return rproc_pta_verify_digest(param_types, params); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +/* + * Pseudo Trusted Application entry points + */ +static TEE_Result rproc_pta_open_session(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + void **sess_ctx __unused) +{ + struct ts_session *s = ts_get_calling_session(); + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct ts_ctx *ctx = NULL; + TEE_UUID ta_uuid = TA_REMOTEPROC_UUID; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + /* Check that we're called by the remoteproc Trusted application*/ + ctx = s->ctx; + if (memcmp(&ctx->uuid, &ta_uuid, sizeof(TEE_UUID))) + return TEE_ERROR_ACCESS_DENIED; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + return TEE_SUCCESS; +} + +pseudo_ta_register(.uuid = PTA_RPROC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = rproc_pta_invoke_command, + .open_session_entry_point = rproc_pta_open_session); diff --git a/core/pta/stm32mp/rproc_pub_key.h b/core/pta/stm32mp/rproc_pub_key.h new file mode 100644 index 0000000000000000000000000000000000000000..b362565237329e902766d7cfaa4704672c2e12ee --- /dev/null +++ b/core/pta/stm32mp/rproc_pub_key.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef PTA_STM32MP_RPROC_PUB_KEY_H +#define PTA_STM32MP_RPROC_PUB_KEY_H + +#include <types_ext.h> + +extern const uint32_t rproc_pub_key_exponent; +extern const uint8_t rproc_pub_key_modulus[]; +extern const size_t rproc_pub_key_modulus_size; + +#endif /* PTA_STM32MP_RPROC_PUB_KEY_H */ + diff --git a/core/pta/stm32mp/sub.mk b/core/pta/stm32mp/sub.mk index ed16c5f471c19957bf7aedbad1aa2f809a84f13b..53a738d6ba23000b22e1b64c2be20916c54bf1f6 100644 --- a/core/pta/stm32mp/sub.mk +++ b/core/pta/stm32mp/sub.mk @@ -1 +1,2 @@ srcs-$(CFG_STM32_BSEC_PTA) += bsec_pta.c +srcs-$(CFG_REMOTEPROC_PTA) += remoteproc_pta.c diff --git a/core/pta/sub.mk b/core/pta/sub.mk index 41212d338b111aaa7eb4b0cd256042a2ad2ac5f0..cf8e86298db49b753bbe141f68474ae8279a41ad 100644 --- a/core/pta/sub.mk +++ b/core/pta/sub.mk @@ -19,3 +19,12 @@ subdirs-y += bcm subdirs-y += stm32mp subdirs-y += imx subdirs-y += k3 + +ifeq ($(CFG_REMOTEPROC_PTA),y) +gensrcs-y += rproc_pub_key +produce-rproc_pub_key = rproc_pub_key.c +depends-rproc_pub_key = $(RPROC_SIGN_KEY) scripts/pem_to_pub_c.py +recipe-rproc_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py \ + --prefix rproc_pub_key --key $(RPROC_SIGN_KEY) \ + --out $(sub-dir-out)/rproc_pub_key.c +endif \ No newline at end of file diff --git a/core/tee/tee_pobj.c b/core/tee/tee_pobj.c index d8a2d267cd92881263f6c5acbc310e34ef08776b..cabf49df756d7d5d0f812b60d9e96d8bdc4ad18c 100644 --- a/core/tee/tee_pobj.c +++ b/core/tee/tee_pobj.c @@ -12,6 +12,26 @@ static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs = TAILQ_HEAD_INITIALIZER(tee_pobjs); static struct mutex pobjs_mutex = MUTEX_INITIALIZER; +static struct mutex pobjs_usage_mutex = MUTEX_INITIALIZER; + +static bool pobj_need_usage_lock(struct tee_pobj *obj) +{ + /* Only lock if we don't have exclusive access to the object */ + return obj->flags & (TEE_DATA_FLAG_SHARE_WRITE | + TEE_DATA_FLAG_SHARE_READ); +} + +void tee_pobj_lock_usage(struct tee_pobj *obj) +{ + if (pobj_need_usage_lock(obj)) + mutex_lock(&pobjs_usage_mutex); +} + +void tee_pobj_unlock_usage(struct tee_pobj *obj) +{ + if (pobj_need_usage_lock(obj)) + mutex_unlock(&pobjs_usage_mutex); +} static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags) { diff --git a/core/tee/tee_ree_fs.c b/core/tee/tee_ree_fs.c index 71d5dcdaa13a08df327fb00a147720d0171fa9bb..2e44ec48da90dc836a9dc0c03fc601920267c0b4 100644 --- a/core/tee/tee_ree_fs.c +++ b/core/tee/tee_ree_fs.c @@ -598,7 +598,7 @@ static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh) static bool once; if (res != TEE_ERROR_NOT_IMPLEMENTED || - !IS_ENABLED(CFG_WARN_INSECURE)) + !IS_ENABLED(CFG_INSECURE)) return res; if (!once) { @@ -633,7 +633,7 @@ static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) if (res) return res; res = nv_counter_incr_ree_fs_to(counter); - if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_WARN_INSECURE)) { + if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_INSECURE)) { static bool once; if (!once) { diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c index 516e3be4f04f0733be319d72d68828b7d509862b..0ed30933b3f301c225e70ef805c4a1f1b8744775 100644 --- a/core/tee/tee_rpmb_fs.c +++ b/core/tee/tee_rpmb_fs.c @@ -75,7 +75,7 @@ struct rpmb_fat_entry { uint32_t start_address; uint32_t data_size; uint32_t flags; - uint32_t write_counter; + uint32_t unused; uint8_t fek[TEE_FS_KM_FEK_SIZE]; char filename[TEE_RPMB_FS_FILENAME_LENGTH]; }; @@ -1518,35 +1518,6 @@ func_exit: return res; } -/* - * Read the RPMB write counter. - * - * @dev_id Device ID of the eMMC device. - * @counter Pointer to the counter. - */ -static TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id, - uint32_t *counter) -{ - TEE_Result res = TEE_SUCCESS; - - if (!counter) - return TEE_ERROR_BAD_PARAMETERS; - - if (rpmb_dead) - return TEE_ERROR_COMMUNICATION; - - if (!rpmb_ctx || !rpmb_ctx->wr_cnt_synced) { - res = tee_rpmb_init(dev_id); - if (res != TEE_SUCCESS) - goto func_exit; - } - - *counter = rpmb_ctx->wr_cnt; - -func_exit: - return res; -} - /* * Read the RPMB max block. * @@ -1986,8 +1957,7 @@ static struct rpmb_file_handle *alloc_file_handle(struct tee_pobj *po, /** * write_fat_entry: Store info in a fat_entry to RPMB. */ -static TEE_Result write_fat_entry(struct rpmb_file_handle *fh, - bool update_write_counter) +static TEE_Result write_fat_entry(struct rpmb_file_handle *fh) { TEE_Result res = TEE_ERROR_GENERIC; @@ -2002,13 +1972,6 @@ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh, goto out; } - if (update_write_counter) { - res = tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID, - &fh->fat_entry.write_counter); - if (res) - goto out; - } - res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address, (uint8_t *)&fh->fat_entry, sizeof(struct rpmb_fat_entry), NULL, NULL); @@ -2114,15 +2077,10 @@ static TEE_Result rpmb_fs_setup(void) fh->rpmb_fat_address = partition_data->fat_start_address; /* Write init FAT entry and partition data to RPMB. */ - res = write_fat_entry(fh, true); + res = write_fat_entry(fh); if (res != TEE_SUCCESS) goto out; - res = - tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID, - &partition_data->write_counter); - if (res != TEE_SUCCESS) - goto out; res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, sizeof(struct rpmb_fs_partition), NULL, NULL); @@ -2277,7 +2235,7 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) memset(&last_fh, 0, sizeof(last_fh)); last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY; last_fh.rpmb_fat_address = fat_address; - res = write_fat_entry(&last_fh, true); + res = write_fat_entry(&last_fh); if (res != TEE_SUCCESS) goto out; } @@ -2364,7 +2322,7 @@ static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh, (void *)fh->fat_entry.fek); DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek)); - res = write_fat_entry(fh, true); + res = write_fat_entry(fh); if (res != TEE_SUCCESS) goto out; } @@ -2595,7 +2553,7 @@ static TEE_Result rpmb_fs_write_primitive(struct rpmb_file_handle *fh, fh->fat_entry.data_size = new_size; fh->fat_entry.start_address = new_fat_entry; - res = write_fat_entry(fh, true); + res = write_fat_entry(fh); } } @@ -2649,7 +2607,7 @@ static TEE_Result rpmb_fs_remove_internal(struct rpmb_file_handle *fh) /* Clear this file entry. */ memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); - return write_fat_entry(fh, false); + return write_fat_entry(fh); } static TEE_Result rpmb_fs_remove(struct tee_pobj *po) @@ -2714,7 +2672,7 @@ static TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old, /* Clear this file entry. */ memset(&fh_new->fat_entry, 0, sizeof(struct rpmb_fat_entry)); - res = write_fat_entry(fh_new, false); + res = write_fat_entry(fh_new); if (res != TEE_SUCCESS) goto out; } @@ -2723,7 +2681,7 @@ static TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old, memcpy(fh_old->fat_entry.filename, fh_new->filename, strlen(fh_new->filename)); - res = write_fat_entry(fh_old, false); + res = write_fat_entry(fh_old); out: free(fh_old); @@ -2815,7 +2773,7 @@ static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length) /* fh->pos is unchanged */ fh->fat_entry.data_size = newsize; fh->fat_entry.start_address = newaddr; - res = write_fat_entry(fh, true); + res = write_fat_entry(fh); out: mutex_unlock(&rpmb_mutex); diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c index f4158dca1517d4afbd05777bbc4b2cfe0d5b802e..237a27de9238ab5940e6c9d43cb6ebcd97cce6e9 100644 --- a/core/tee/tee_svc.c +++ b/core/tee/tee_svc.c @@ -700,11 +700,13 @@ static TEE_Result tee_svc_copy_param(struct ts_session *sess, case TEE_PARAM_TYPE_MEMREF_INOUT: va = (void *)param->u[n].mem.offs; s = param->u[n].mem.size; - if (!va) { - if (s) - return TEE_ERROR_BAD_PARAMETERS; + if (!s) { + param->u[n].mem.mobj = NULL; break; } + if (!va) + return TEE_ERROR_BAD_PARAMETERS; + /* uTA cannot expose its private memory */ if (vm_buf_is_inside_um_private(&utc->uctx, va, s)) return TEE_ERROR_BAD_PARAMETERS; diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c index 72503454bce45a73b10e0200ca2fc2732e5e81e8..5a16ee4d65d4f6dd780e4eced860d6d24385e28b 100644 --- a/core/tee/tee_svc_cryp.c +++ b/core/tee/tee_svc_cryp.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. - * Copyright (c) 2020, 2022 Linaro Limited + * Copyright (c) 2020, 2022-2023 Linaro Limited * Copyright (c) 2022, Technology Innovation Institute (TII) */ @@ -22,7 +22,9 @@ #include <tee_api_types.h> #include <tee/tee_cryp_utl.h> #include <tee/tee_obj.h> +#include <tee/tee_pobj.h> #include <tee/tee_svc_cryp.h> +#include <tee/tee_svc_storage.h> #include <tee/tee_svc.h> #include <trace.h> #include <utee_defines.h> @@ -1184,7 +1186,13 @@ TEE_Result syscall_cryp_obj_get_info(unsigned long obj, o_info.obj_type = o->info.objectType; o_info.obj_size = o->info.objectSize; o_info.max_obj_size = o->info.maxObjectSize; - o_info.obj_usage = o->info.objectUsage; + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(o->pobj); + o_info.obj_usage = o->pobj->obj_info_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + o_info.obj_usage = o->info.objectUsage; + } o_info.data_size = o->info.dataSize; o_info.data_pos = o->info.dataPosition; o_info.handle_flags = o->info.handleFlags; @@ -1202,12 +1210,22 @@ TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj, struct tee_obj *o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); - if (res != TEE_SUCCESS) - goto exit; + if (res) + return res; - o->info.objectUsage &= usage; + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + uint32_t new_usage = 0; + + tee_pobj_lock_usage(o->pobj); + new_usage = o->pobj->obj_info_usage & usage; + res = tee_svc_storage_write_usage(o, new_usage); + if (!res) + o->pobj->obj_info_usage = new_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + o->info.objectUsage &= usage; + } -exit: return res; } @@ -1271,6 +1289,7 @@ TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, int idx = 0; const struct attr_ops *ops = NULL; void *attr = NULL; + uint32_t obj_usage = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) @@ -1281,9 +1300,17 @@ TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, return TEE_ERROR_BAD_PARAMETERS; /* Check that getting the attribute is allowed */ - if (!(attr_id & TEE_ATTR_FLAG_PUBLIC) && - !(o->info.objectUsage & TEE_USAGE_EXTRACTABLE)) - return TEE_ERROR_BAD_PARAMETERS; + if (!(attr_id & TEE_ATTR_FLAG_PUBLIC)) { + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(o->pobj); + obj_usage = o->pobj->obj_info_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + obj_usage = o->info.objectUsage; + } + if (!(obj_usage & TEE_USAGE_EXTRACTABLE)) + return TEE_ERROR_BAD_PARAMETERS; + } type_props = tee_svc_find_type_props(o->info.objectType); if (!type_props) { @@ -1619,7 +1646,10 @@ TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type, o->info.objectType = obj_type; o->info.maxObjectSize = max_key_size; - o->info.objectUsage = TEE_USAGE_DEFAULT; + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) + o->pobj->obj_info_usage = TEE_USAGE_DEFAULT; + else + o->info.objectUsage = TEE_USAGE_DEFAULT; return TEE_SUCCESS; } @@ -2040,7 +2070,13 @@ TEE_Result syscall_cryp_obj_copy(unsigned long dst, unsigned long src) dst_o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; dst_o->info.objectSize = src_o->info.objectSize; - dst_o->info.objectUsage = src_o->info.objectUsage; + if (src_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(src_o->pobj); + dst_o->info.objectUsage = src_o->pobj->obj_info_usage; + tee_pobj_unlock_usage(src_o->pobj); + } else { + dst_o->info.objectUsage = src_o->info.objectUsage; + } return TEE_SUCCESS; } diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c index 3adf62dde7249b3285ca3b1de55f9702f6d7fbeb..5cf39d567dbe5a53e46b320f0fb07c15b6ecaa39 100644 --- a/core/tee/tee_svc_storage.c +++ b/core/tee/tee_svc_storage.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. - * Copyright (c) 2020, 2022 Linaro Limited + * Copyright (c) 2020, 2022-2023 Linaro Limited */ #include <config.h> @@ -150,7 +150,7 @@ static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) o->info.dataSize = size - sizeof(head) - head.attr_size; o->info.objectSize = head.objectSize; - o->info.objectUsage = head.objectUsage; + o->pobj->obj_info_usage = head.objectUsage; o->info.objectType = head.objectType; o->have_attrs = head.have_attrs; @@ -214,7 +214,9 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, o->pobj = po; tee_obj_add(utc, o); + tee_pobj_lock_usage(o->pobj); res = tee_svc_storage_read_head(o); + tee_pobj_unlock_usage(o->pobj); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); @@ -263,7 +265,7 @@ static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite, if (res) return res; o->have_attrs = attr_o->have_attrs; - o->info.objectUsage = attr_o->info.objectUsage; + o->pobj->obj_info_usage = attr_o->info.objectUsage; o->info.objectSize = attr_o->info.objectSize; } res = tee_obj_attr_to_binary(o, NULL, &attr_size); @@ -289,7 +291,7 @@ static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite, head.attr_size = attr_size; head.objectSize = o->info.objectSize; head.maxObjectSize = o->info.maxObjectSize; - head.objectUsage = o->info.objectUsage; + head.objectUsage = o->pobj->obj_info_usage; head.objectType = o->info.objectType; head.have_attrs = o->have_attrs; @@ -369,12 +371,16 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, /* * The caller expects the supplied attributes handle to be * transformed into a persistent object. + * + * Persistent object keeps the objectUsage field in the + * pobj so move the field below. */ uint32_t saved_flags = attr_o->info.handleFlags; attr_o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | flags; attr_o->pobj = po; + po->obj_info_usage = attr_o->info.objectUsage; res = tee_svc_storage_init_file(attr_o, flags & TEE_DATA_FLAG_OVERWRITE, attr_o, data, len); @@ -383,6 +389,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, attr_o->pobj = NULL; goto err; } + attr_o->info.objectUsage = 0; } else { o = tee_obj_alloc(); if (!o) { @@ -667,19 +674,21 @@ TEE_Result syscall_storage_next_enum(unsigned long obj_enum, o->info.handleFlags = o->pobj->flags | TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; + tee_pobj_lock_usage(o->pobj); res = tee_svc_storage_read_head(o); - if (res != TEE_SUCCESS) - goto exit; - bbuf = (struct utee_object_info){ .obj_type = o->info.objectType, .obj_size = o->info.objectSize, .max_obj_size = o->info.maxObjectSize, - .obj_usage = o->info.objectUsage, + .obj_usage = o->pobj->obj_info_usage, .data_size = o->info.dataSize, .data_pos = o->info.dataPosition, .handle_flags = o->info.handleFlags, }; + tee_pobj_unlock_usage(o->pobj); + if (res != TEE_SUCCESS) + goto exit; + res = copy_to_user(info, &bbuf, sizeof(bbuf)); if (res) goto exit; @@ -809,6 +818,13 @@ exit: return res; } +TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage) +{ + const size_t pos = offsetof(struct tee_svc_storage_head, objectUsage); + + return o->pobj->fops->write(o->fh, pos, &usage, NULL, sizeof(usage)); +} + TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) { struct ts_session *sess = ts_get_current_session(); diff --git a/ldelf/ta_elf.c b/ldelf/ta_elf.c index cf802ac8acfe527a30d5104fd734daabd7b818e8..4e11e00ad75eff9cac28fda7becab707ebe00bd3 100644 --- a/ldelf/ta_elf.c +++ b/ldelf/ta_elf.c @@ -104,9 +104,9 @@ static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr) if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || - ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE && + ehdr->e_ident[EI_OSABI] != ELFOSABI_ARM) || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || - (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION || #ifndef CFG_WITH_VFP (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) || #endif @@ -114,6 +114,14 @@ static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr) ehdr->e_shentsize != sizeof(Elf32_Shdr)) return TEE_ERROR_BAD_FORMAT; + if (ehdr->e_ident[EI_OSABI] == ELFOSABI_NONE && + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_V5) + return TEE_ERROR_BAD_FORMAT; + + if (ehdr->e_ident[EI_OSABI] == ELFOSABI_ARM && + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_UNKNOWN) + return TEE_ERROR_BAD_FORMAT; + elf->is_32bit = true; elf->e_entry = ehdr->e_entry; elf->e_phoff = ehdr->e_phoff; diff --git a/lib/libmbedtls/core/ecc.c b/lib/libmbedtls/core/ecc.c index 39adf0e3397c016f79dc0d5cb72628433b869365..38585573ef2ca0a8e6b765ff5606293e3ac68213 100644 --- a/lib/libmbedtls/core/ecc.c +++ b/lib/libmbedtls/core/ecc.c @@ -228,7 +228,7 @@ static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key, mbedtls_mpi_size(&s)); res = TEE_SUCCESS; } else { - FMSG("mbedtls_ecdsa_sign failed, returned 0x%x\n", -lmd_res); + FMSG("mbedtls_ecdsa_sign failed, returned 0x%x", -lmd_res); res = TEE_ERROR_GENERIC; } out: diff --git a/lib/libutee/include/elf_common.h b/lib/libutee/include/elf_common.h index 0ac08fafb8633218bca73f4b3c8f054051f4d471..8fe481cbbe521847f349d5583b659d7670b7069f 100644 --- a/lib/libutee/include/elf_common.h +++ b/lib/libutee/include/elf_common.h @@ -260,7 +260,8 @@ typedef struct { #define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ /* e_flags for EM_ARM */ -#define EF_ARM_ABI_VERSION 0x05000000 /* ABI version 5 */ +#define EF_ARM_ABI_UNKNOWN 0x00000000 +#define EF_ARM_ABI_V5 0x05000000 /* ABI version 5 */ #define EF_ARM_ABIMASK 0xFF000000 #define EF_ARM_BE8 0x00800000 #define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ diff --git a/lib/libutee/include/pta_stats.h b/lib/libutee/include/pta_stats.h new file mode 100644 index 0000000000000000000000000000000000000000..f95d3acb8c6afee09749f2da92f1e2054755c39b --- /dev/null +++ b/lib/libutee/include/pta_stats.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + * Copyright (C) 2022, Microchip + */ +#ifndef __PTA_STATS_H +#define __PTA_STATS_H + +#include <stdint.h> +#include <tee_api_types.h> + +#define STATS_UUID \ + { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +/* + * STATS_CMD_PAGER_STATS - Get statistics on pager + * + * [out] value[0].a Number of unlocked pages + * [out] value[0].b Page pool size + * [out] value[1].a R/O faults since last stats dump + * [out] value[1].b R/W faults since last stats dump + * [out] value[2].a Hidden faults since last stats dump + * [out] value[2].b Zi pages released since last stats dump + */ +#define STATS_CMD_PAGER_STATS 0 + +/* + * STATS_CMD_ALLOC_STATS - Get statistics on core heap allocations + * + * [in] value[0].a ID of allocator(s) to get stats from (ALLOC_ID_*) + * [out] memref[0] Array of struct pta_stats_alloc instances + */ +#define STATS_CMD_ALLOC_STATS 1 + +#define ALLOC_ID_ALL 0 /* All allocators */ +#define ALLOC_ID_HEAP 1 /* Core heap allocator */ +#define ALLOC_ID_PUBLIC_DDR 2 /* Public DDR allocator (deprecated) */ +#define ALLOC_ID_TA_RAM 3 /* TA_RAM allocator */ +#define ALLOC_ID_NEXUS_HEAP 4 /* Nexus heap allocator */ +#define STATS_NB_POOLS 5 + +#define TEE_ALLOCATOR_DESC_LENGTH 32 + +struct pta_stats_alloc { + char desc[TEE_ALLOCATOR_DESC_LENGTH]; + uint32_t allocated; /* Bytes currently allocated */ + uint32_t max_allocated; /* Tracks max value of allocated */ + uint32_t size; /* Total size for this allocator */ + uint32_t num_alloc_fail; /* Number of failed alloc requests */ + uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ + uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ +}; + +/* + * STATS_CMD_MEMLEAK_STATS - Print memory leakage info to console + */ +#define STATS_CMD_MEMLEAK_STATS 2 + +/* + * STATS_CMD_TA_STATS - Get information on TA instances + * + * [out] memref[0] Array of struct pta_stats_ta per loaded TA + */ +#define STATS_CMD_TA_STATS 3 + +struct pta_stats_ta { + TEE_UUID uuid; + uint32_t panicked; /* True if TA has panicked */ + uint32_t sess_num; /* Number of opened session */ + struct pta_stats_alloc heap; +}; + +/* + * STATS_CMD_GET_TIME - Get both REE time and TEE time + * + * [out] value[0].a REE time as seen by OP-TEE in seconds + * [out] value[0].b REE time as seen by OP-TEE, milliseconds part + * [out] value[1].a TEE system time in seconds + * [out] value[1].b TEE system time, milliseconds part + */ +#define STATS_CMD_GET_TIME 4 + +/* + * STATS_CMD_PRINT_DRIVER_INFO - Print device drivers information to console + * + * [in] value[0].a Target driver, one of STATS_DRIVER_TYPE_* + */ +#define STATS_CMD_PRINT_DRIVER_INFO 5 + +#define STATS_DRIVER_TYPE_CLOCK 0 +#define STATS_DRIVER_TYPE_REGULATOR 1 + +#endif /*__PTA_STATS_H*/ diff --git a/lib/libutee/include/remoteproc_pta.h b/lib/libutee/include/remoteproc_pta.h new file mode 100644 index 0000000000000000000000000000000000000000..e4be4becd77004b567e2325af88830b92f9b9bd8 --- /dev/null +++ b/lib/libutee/include/remoteproc_pta.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef __REMOTEPROC_PTA_H +#define __REMOTEPROC_PTA_H + +#include <stdint.h> +#include <util.h> + +/* + * Interface to the pseudo TA which provides platform implementation + * of the remote processor management + */ + +#define PTA_RPROC_UUID { 0x54af4a68, 0x19be, 0x40d7, \ + { 0xbb, 0xe6, 0x89, 0x50, 0x35, 0x0a, 0x87, 0x44 } } + +/* Hardware capability: firmware format */ +#define PTA_RPROC_HWCAP_FMT_ELF BIT32(0) + +/* Hardware capability: image protection method */ +/* The platform supports load of segment with hash protection */ +#define PTA_RPROC_HWCAP_PROT_HASH_TABLE BIT32(0) + +/** + * struct rproc_pta_key_info - public key information + * @algo: Algorithm, defined by public key algorithms TEE_ALG_* + * @info_size: Byte size of @info + * @info: Append key information data + */ +struct rproc_pta_key_info { + uint32_t algo; + uint32_t info_size; + uint8_t info[]; +}; + +static inline size_t rproc_pta_keyinfo_size(struct rproc_pta_key_info *keyinf) +{ + size_t s = 0; + + if (!keyinf || ADD_OVERFLOW(sizeof(*keyinf), keyinf->info_size, &s)) + return 0; + + return s; +} + +/* + * Platform capabilities. + * + * Get Platform firmware loader service capabilities. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].value.a: Firmware format (PTA_RPROC_HWCAP_FMT_*) + * [out] params[2].value.a: Image protection method (PTA_RPROC_HWCAP_PROT_*) + */ +#define PTA_RPROC_HW_CAPABILITIES 1 + +/* + * Firmware loading. + * + * Optional service to implement only in case of proprietary format. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Loadable firmware image + */ +#define PTA_RPROC_FIRMWARE_LOAD 2 + +/* + * Load a segment with a SHA256 hash. + * + * This command is used when the platform secure memory is too constrained to + * save the whole firmware image. Upon segment load, a successful completion + * ensures the loaded image complies with the provided hash. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Section data to load + * [in] params[2].value.a: 32bit LSB load device segment address + * [in] params[2].value.b: 32bit MSB load device segment address + * [in] params[3].memref: Expected hash (SHA256) of the payload + */ +#define PTA_RPROC_LOAD_SEGMENT_SHA256 3 + +/* + * Memory set. + * + * Fill a remote device memory with requested value. this is used for instance + * to clear a memory on the remote firmware load. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].value.a: 32bit LSB device memory address + * [in] params[1].value.b: 32bit MSB device memory address + * [in] params[2].value.a: 32bit LSB device memory size + * [in] params[2].value.b: 32bit MSB device memory size + * [in] params[3].value.a: Byte value to be set + */ +#define PTA_RPROC_SET_MEMORY 4 + +/* + * Firmware start. + * + * Start up a successfully loaded remote processor firmware. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define PTA_RPROC_FIRMWARE_START 5 + +/* + * Firmware stop. + * + * Stop of the remote processor firmware and release/clean resources. + * After the command successful completion, remote processor firmware must be + * reloaded prior being started again. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define PTA_RPROC_FIRMWARE_STOP 6 + +/* + * Firmware device to physical address conversion. + * + * Convert the physical address corresponding to an address got from the + * firmware address layout. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].value.a: 32bit LSB Device memory address + * [in] params[1].value.b: 32bit MSB Device memory address + * [in] params[2].value.a: 32bit LSB Device memory size + * [in] params[2].value.b: 32bit MSB Device memory size + * [out] params[3].value.a: 32bit LSB converted physical address + * [out] params[3].value.b: 32bit MSB converted physical address + */ +#define PTA_RPROC_FIRMWARE_DA_TO_PA 7 + +/* + * Verify the firmware digest against a signature + * + * Return TEE_SUCCESS if the signature is verified, + * TEE_ERROR_SIGNATURE_INVALID when signature is not valid, + * another error code for other error cases. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Key information (refer to @rproc_pta_key_info) + * [in] params[2].memref: Digest of the firmware authenticated data + * [in] params[3].memref: Signature of the firmware authenticated data + */ +#define PTA_RPROC_VERIFY_DIGEST 8 + +#endif /* __REMOTEPROC_PTA_H */ diff --git a/lib/libutee/include/tee_arith_internal.h b/lib/libutee/include/tee_arith_internal.h index fc5678edc2021287891cecf86843e9b31943f827..cf1d3edd7e1af5e960f16e9d26a790d46e35af50 100644 --- a/lib/libutee/include/tee_arith_internal.h +++ b/lib/libutee/include/tee_arith_internal.h @@ -22,12 +22,6 @@ */ #define TEE_MATHAPI_EXPORT -/* - * The modes for String Conversion - */ -#define TEE_STRING_MODE_HEX_UC MPA_STRING_MODE_HEX_UC -#define TEE_STRING_MODE_HEX_LC MPA_STRING_MODE_HEX_UC - /*------------------------------------------------------------ * * Define IN, OUT, INBUF and OUTBUF to keep format from the spec. diff --git a/lib/libutee/include/utee_defines.h b/lib/libutee/include/utee_defines.h index 8a3ccf34b73ffa6890dd1383d70d00112a2adb33..6c3248d178d6f6c6c7107eb5ce74b8345e88cf45 100644 --- a/lib/libutee/include/utee_defines.h +++ b/lib/libutee/include/utee_defines.h @@ -302,12 +302,18 @@ static inline size_t __tee_alg_get_digest_size(uint32_t algo) #endif /* If we we're on a big endian platform we'll have to update these */ -#define TEE_U64_FROM_BIG_ENDIAN(x) TEE_U64_BSWAP(x) -#define TEE_U32_FROM_BIG_ENDIAN(x) TEE_U32_BSWAP(x) -#define TEE_U16_FROM_BIG_ENDIAN(x) TEE_U16_BSWAP(x) -#define TEE_U64_TO_BIG_ENDIAN(x) TEE_U64_BSWAP(x) -#define TEE_U32_TO_BIG_ENDIAN(x) TEE_U32_BSWAP(x) -#define TEE_U16_TO_BIG_ENDIAN(x) TEE_U16_BSWAP(x) +#define TEE_U64_FROM_LITTLE_ENDIAN(x) ((uint64_t)(x)) +#define TEE_U32_FROM_LITTLE_ENDIAN(x) ((uint32_t)(x)) +#define TEE_U16_FROM_LITTLE_ENDIAN(x) ((uint16_t)(x)) +#define TEE_U64_TO_LITTLE_ENDIAN(x) ((uint64_t)(x)) +#define TEE_U32_TO_LITTLE_ENDIAN(x) ((uint32_t)(x)) +#define TEE_U16_TO_LITTLE_ENDIAN(x) ((uint16_t)(x)) +#define TEE_U64_FROM_BIG_ENDIAN(x) TEE_U64_BSWAP(x) +#define TEE_U32_FROM_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_FROM_BIG_ENDIAN(x) TEE_U16_BSWAP(x) +#define TEE_U64_TO_BIG_ENDIAN(x) TEE_U64_BSWAP(x) +#define TEE_U32_TO_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_TO_BIG_ENDIAN(x) TEE_U16_BSWAP(x) #define TEE_TIME_MILLIS_BASE 1000 diff --git a/lib/libutee/tee_api_arith_mpi.c b/lib/libutee/tee_api_arith_mpi.c index 5842f13a807c05318a87f46d46340a40f40fe555..9ccbd7c68073467fcf453df9b4e33577e45a1dab 100644 --- a/lib/libutee/tee_api_arith_mpi.c +++ b/lib/libutee/tee_api_arith_mpi.c @@ -726,10 +726,6 @@ out: return res; } -/* - * Based on libmpa implementation __mpa_egcd(), modified to work with MPI - * instead. - */ static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, mbedtls_mpi *x_in, mbedtls_mpi *y_in) { diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c index f44350da2f794dda1980044bb4361c32cd097d11..752425ae9627a2b3b35373143510c84b3abc40c9 100644 --- a/lib/libutee/tee_api_operations.c +++ b/lib/libutee/tee_api_operations.c @@ -132,7 +132,7 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, break; } - /* Check algorithm mode (and maxKeySize for digests) */ + /* Check algorithm mode */ switch (algorithm) { case TEE_ALG_AES_CTS: case TEE_ALG_AES_XTS: @@ -277,8 +277,6 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, case TEE_ALG_SM3: if (mode != TEE_MODE_DIGEST) return TEE_ERROR_NOT_SUPPORTED; - if (maxKeySize) - return TEE_ERROR_NOT_SUPPORTED; /* v1.1: flags always set for digest operations */ handle_state |= TEE_HANDLE_FLAG_KEY_SET; req_key_usage = 0; diff --git a/lib/libutee/user_ta_entry.c b/lib/libutee/user_ta_entry.c index 2ac3e25588b830d8e6bfb9e73bb61ad42b73381f..b33953f429e2e79a4deb2e753926b11b9c43ed95 100644 --- a/lib/libutee/user_ta_entry.c +++ b/lib/libutee/user_ta_entry.c @@ -392,7 +392,7 @@ static TEE_Result entry_dump_memstats(unsigned long session_id __unused, { uint32_t param_types = 0; TEE_Param params[TEE_NUM_PARAMS] = { }; - struct malloc_stats stats = { }; + struct pta_stats_alloc stats = { }; from_utee_params(params, ¶m_types, up); ta_header_save_params(param_types, params); diff --git a/lib/libutils/ext/include/trace.h b/lib/libutils/ext/include/trace.h index 6f28bdb771fa5b465a9e6c45cf60b093b2c6ebeb..6ea6dcc6cd021556e65f983aaff614cfe60194c7 100644 --- a/lib/libutils/ext/include/trace.h +++ b/lib/libutils/ext/include/trace.h @@ -26,6 +26,7 @@ extern const char trace_ext_prefix[]; void trace_ext_puts(const char *str); int trace_ext_get_thread_id(void); int trace_ext_get_core_id(void); +int trace_ext_get_guest_id(void); void trace_set_level(int level); int trace_get_level(void); void plat_trace_ext_puts(const char *str); diff --git a/lib/libutils/ext/mempool.c b/lib/libutils/ext/mempool.c index 30508aad0389752fc31d6acd6c2df6eabb59f4fe..e12962f0eeede8a87c36fed6763c6dbd8978f4c9 100644 --- a/lib/libutils/ext/mempool.c +++ b/lib/libutils/ext/mempool.c @@ -9,6 +9,7 @@ #include <compiler.h> #include <malloc.h> #include <mempool.h> +#include <pta_stats.h> #include <string.h> #include <util.h> @@ -146,7 +147,7 @@ void *mempool_alloc(struct mempool *pool, size_t size) p = raw_malloc(0, 0, size, pool->mctx); if (p) { #ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET - struct malloc_stats stats = { }; + struct pta_stats_alloc stats = { }; raw_malloc_get_stats(pool->mctx, &stats); if (stats.max_allocated > pool->max_allocated) { diff --git a/lib/libutils/ext/trace.c b/lib/libutils/ext/trace.c index 33c099d2c1975d8de2cc025f2f5a4d4e9b815df7..259e4a7af77adacd973d7a29f3e49a81dfb2ece2 100644 --- a/lib/libutils/ext/trace.c +++ b/lib/libutils/ext/trace.c @@ -7,12 +7,13 @@ #include <platform_config.h> #endif +#include <config.h> #include <printk.h> #include <stdarg.h> #include <string.h> #include <trace.h> -#include <util.h> #include <types_ext.h> +#include <util.h> #if (TRACE_LEVEL < TRACE_MIN) || (TRACE_LEVEL > TRACE_MAX) #error "Invalid value of TRACE_LEVEL" @@ -91,11 +92,26 @@ static int print_core_id(char *buf, size_t bs) else return snprintk(buf, bs, "%s ", qm); } + +static int print_guest_id(char *buf, size_t bs) +{ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + return snprintk(buf, bs, "%d ", trace_ext_get_guest_id()); + else + return 0; + + +} #else /* defined(__KERNEL__) */ static int print_core_id(char *buf __unused, size_t bs __unused) { return 0; } + +static int print_guest_id(char *buf __unused, size_t bs __unused) +{ + return 0; +} #endif /* Format trace of user ta. Inline with kernel ta */ @@ -133,6 +149,12 @@ void trace_vprintf(const char *function, int line, int level, bool level_ok, boffs += res; if (level_ok && (BIT(level) & CFG_MSG_LONG_PREFIX_MASK)) { + /* Print the current guest ID or 0 for Nexus */ + res = print_guest_id(buf + boffs, sizeof(buf) - boffs); + if (res < 0) + return; + boffs += res; + /* Print the core ID if in atomic context */ res = print_core_id(buf + boffs, sizeof(buf) - boffs); if (res < 0) diff --git a/lib/libutils/isoc/bget_malloc.c b/lib/libutils/isoc/bget_malloc.c index 15745bbbc8f4a099c9e7356541f9eceb28b1e4d6..1b26f93c8143bf10741b00e103de23143bf3a90e 100644 --- a/lib/libutils/isoc/bget_malloc.c +++ b/lib/libutils/isoc/bget_malloc.c @@ -82,6 +82,7 @@ #include <config.h> #include <malloc.h> #include <memtag.h> +#include <pta_stats.h> #include <stdbool.h> #include <stdint.h> #include <stdlib_ext.h> @@ -135,7 +136,7 @@ struct malloc_ctx { struct malloc_pool *pool; size_t pool_len; #ifdef BufStats - struct malloc_stats mstats; + struct pta_stats_alloc mstats; #endif #ifdef __KERNEL__ unsigned int spinlock; @@ -308,7 +309,7 @@ void malloc_reset_stats(void) } static void gen_malloc_get_stats(struct malloc_ctx *ctx, - struct malloc_stats *stats) + struct pta_stats_alloc *stats) { uint32_t exceptions = malloc_lock(ctx); @@ -316,7 +317,7 @@ static void gen_malloc_get_stats(struct malloc_ctx *ctx, malloc_unlock(ctx, exceptions); } -void malloc_get_stats(struct malloc_stats *stats) +void malloc_get_stats(struct pta_stats_alloc *stats) { gen_malloc_get_stats(&malloc_ctx, stats); } @@ -711,7 +712,7 @@ static void gen_mdbg_check(struct malloc_ctx *ctx, int bufdump) if (!fname) fname = "unknown"; - IMSG("buffer: %d bytes %s:%d\n", + IMSG("buffer: %d bytes %s:%d", hdr->pl_size, fname, hdr->line); } } @@ -996,7 +997,7 @@ bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, } #ifdef CFG_WITH_STATS -void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats) +void raw_malloc_get_stats(struct malloc_ctx *ctx, struct pta_stats_alloc *stats) { memcpy_unchecked(stats, &ctx->mstats, sizeof(*stats)); stats->allocated = ctx->poolset.totalloc; @@ -1130,7 +1131,7 @@ void nex_malloc_reset_stats(void) gen_malloc_reset_stats(&nex_malloc_ctx); } -void nex_malloc_get_stats(struct malloc_stats *stats) +void nex_malloc_get_stats(struct pta_stats_alloc *stats) { gen_malloc_get_stats(&nex_malloc_ctx, stats); } diff --git a/lib/libutils/isoc/include/malloc.h b/lib/libutils/isoc/include/malloc.h index d26195585e3169f4143a6ca372a31995d39bdfd4..4e405c03c763044db270363fd8970f4cbe34e696 100644 --- a/lib/libutils/isoc/include/malloc.h +++ b/lib/libutils/isoc/include/malloc.h @@ -5,6 +5,7 @@ #ifndef __MALLOC_H #define __MALLOC_H +#include <pta_stats.h> #include <stddef.h> #include <types_ext.h> @@ -80,22 +81,8 @@ bool malloc_buffer_overlaps_heap(void *buf, size_t len); void malloc_add_pool(void *buf, size_t len); #ifdef CFG_WITH_STATS -/* - * Get/reset allocation statistics - */ - -#define TEE_ALLOCATOR_DESC_LENGTH 32 -struct malloc_stats { - char desc[TEE_ALLOCATOR_DESC_LENGTH]; - uint32_t allocated; /* Bytes currently allocated */ - uint32_t max_allocated; /* Tracks max value of allocated */ - uint32_t size; /* Total size for this allocator */ - uint32_t num_alloc_fail; /* Number of failed alloc requests */ - uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ - uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ -}; - -void malloc_get_stats(struct malloc_stats *stats); +/* Get/reset allocation statistics */ +void malloc_get_stats(struct pta_stats_alloc *stats); void malloc_reset_stats(void); #endif /* CFG_WITH_STATS */ @@ -142,7 +129,7 @@ void nex_malloc_add_pool(void *buf, size_t len); * Get/reset allocation statistics */ -void nex_malloc_get_stats(struct malloc_stats *stats); +void nex_malloc_get_stats(struct pta_stats_alloc *stats); void nex_malloc_reset_stats(void); #endif /* CFG_WITH_STATS */ @@ -174,7 +161,8 @@ bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, void *buf, size_t len); #ifdef CFG_WITH_STATS -void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats); +void raw_malloc_get_stats(struct malloc_ctx *ctx, + struct pta_stats_alloc *stats); #endif #endif /* __MALLOC_H */ diff --git a/mk/aosp_optee.mk b/mk/aosp_optee.mk index 07bc67ab4c743f07129ca46b41cf127590665039..65cd4a51aa4cb0c9c606c7b91bb9a30aada84e6a 100644 --- a/mk/aosp_optee.mk +++ b/mk/aosp_optee.mk @@ -60,7 +60,8 @@ TA_TARGET := $(local_optee_ta_target) else TA_TARGET := $(OPTEE_TA_TARGETS) endif -TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) +TA_DEV_KIT_DIR := $(OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) +ABS_TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) CROSS_COMPILE64 ?= $(TOP_ROOT_ABS)/$(TARGET_TOOLS_PREFIX) CROSS_COMPILE_LINE := CROSS_COMPILE64="$(CROSS_COMPILE64)" @@ -73,6 +74,10 @@ OPTEE_BIN := $(OPTEE_OS_OUT_DIR)/core/tee.bin $(OPTEE_BIN) : $(sort $(shell find -L $(OPTEE_OS_DIR))) +OPTEE_TA_DEV_KIT_MK := $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +$(OPTEE_TA_DEV_KIT_MK) : $(sort $(shell find -L $(OPTEE_OS_DIR))) + ########################################################### ## define making rules for $(OPTEE_BIN) target, and add ## ## condition check to make it only be defined once ## @@ -99,6 +104,27 @@ $(OPTEE_BIN): endif +########################################################### +## similar to the $(OPTEE_BIN) target above, use condition +## check to make $(OPTEE_TA_DEV_KIT_MK) for different ta +## targets only be defined once +########################################################### +ifeq ($(filter $(TA_TARGET),$(BUILD_TA_DEV_KIT_DEFINED)),) +BUILD_TA_DEV_KIT_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_DEFINED) +$(OPTEE_TA_DEV_KIT_MK): PRIVATE_TA_TARGET := $(TA_TARGET) +$(OPTEE_TA_DEV_KIT_MK): + @echo "Start building ta_dev_kit ($(PRIVATE_TA_TARGET))..." + +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ + O=$(ABS_OPTEE_OS_OUT_DIR) \ + CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) \ + CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ + PLATFORM=$(OPTEE_PLATFORM) \ + PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ + $(CROSS_COMPILE_LINE) \ + $(OPTEE_EXTRA_FLAGS) ta_dev_kit + @echo "Finished building ta_dev_kit ($(PRIVATE_TA_TARGET))..." +endif + ########################################################## ## Lines for building TAs automatically ## ## will only be included in Android.mk for TAs ## @@ -133,8 +159,8 @@ $(TA_TMP_FILE): $(TA_TMP_FILE_DEPS) $(TA_TMP_FILE): PRIVATE_TA_SRC_DIR := $(LOCAL_PATH) $(TA_TMP_FILE): PRIVATE_TA_TMP_FILE := $(TA_TMP_FILE) $(TA_TMP_FILE): PRIVATE_TA_TMP_DIR := $(TA_TMP_DIR) -$(TA_TMP_FILE): PRIVATE_TA_DEV_KIT_DIR := $(TA_DEV_KIT_DIR) -$(TA_TMP_FILE): $(OPTEE_BIN) +$(TA_TMP_FILE): PRIVATE_TA_DEV_KIT_DIR := $(ABS_TA_DEV_KIT_DIR) +$(TA_TMP_FILE): $(OPTEE_TA_DEV_KIT_MK) @echo "Start building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(PRIVATE_TA_SRC_DIR) O=$(ABS_OPTEE_TA_OUT_DIR)/$(PRIVATE_TA_TMP_DIR) \ TA_DEV_KIT_DIR=$(PRIVATE_TA_DEV_KIT_DIR) \ @@ -143,6 +169,27 @@ $(TA_TMP_FILE): $(OPTEE_BIN) @echo "Finished building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." include $(BUILD_PREBUILT) + +# To get ta elf files for early-ta, +# copy them to $(PRODUCT_OUT)/unsigned/ on host +ifeq ($(call ta_class,$(local_module)),EXECUTABLES) +include $(CLEAR_VARS) +LOCAL_MODULE := $(local_module).unsigned +LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/unsigned +LOCAL_MODULE_CLASS := $(call ta_class,$(local_module)) +LOCAL_MODULE_TAGS := optional + +TA_TMP_STRIPPED_ELF_FILE := $(patsubst %.ta,%.stripped.elf,$(TA_TMP_FILE)) +$(TA_TMP_STRIPPED_ELF_FILE): $(TA_TMP_FILE) + +$(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_STRIPPED_ELF_FILE) + @mkdir -p $(dir $@) + cp -vf $< $@ + +include $(BUILD_PREBUILT) +endif # to get ta elf files for early-ta + local_module_deps := local_optee_ta_target := endif diff --git a/mk/config.mk b/mk/config.mk index a9a68e3a48db659f71881d6dfe1e7b3937368978..1247ccef935472ef6cb267f884ac464790982040 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -121,7 +121,7 @@ CFG_OS_REV_REPORTS_GIT_SHA1 ?= y # with limited depth not including any tag, so there is really no guarantee # that TEE_IMPL_VERSION contains the major and minor revision numbers. CFG_OPTEE_REVISION_MAJOR ?= 4 -CFG_OPTEE_REVISION_MINOR ?= 0 +CFG_OPTEE_REVISION_MINOR ?= 1 CFG_OPTEE_REVISION_EXTRA ?= # Trusted OS implementation version @@ -359,7 +359,9 @@ $(eval $(call cfg-depends-all,CFG_REE_FS_TA_BUFFERED,CFG_REE_FS_TA)) # anti-rollback errors. That is, rm /data/tee/dirf.db or rm -rf /data/tee (or # whatever path is configured in tee-supplicant as CFG_TEE_FS_PARENT_PATH) # can be used to reset the secure storage to a clean, empty state. -# Typically used for testing only since it weakens storage security. +# Intended to be used for testing only since it weakens storage security. +# Warning: If enabled for release build then it will break rollback protection +# of TAs and the entire REE FS secure storage. CFG_REE_FS_ALLOW_RESET ?= n # Support for loading user TAs from a special section in the TEE binary. @@ -495,6 +497,19 @@ ifeq ($(CFG_MAP_EXT_DT_SECURE),y) $(call force,CFG_DT,y) endif +# This option enables OP-TEE to support boot arguments handover via Transfer +# List defined in Firmware Handoff specification. +# Note: This is an experimental feature and incompatible ABI changes can be +# expected. It should be off by default until Firmware Handoff specification +# has a stable release. +# This feature requires the support of Device Tree. +CFG_TRANSFER_LIST ?= n +ifeq ($(CFG_TRANSFER_LIST),y) +$(call force,CFG_DT,y) +$(call force,CFG_EXTERNAL_DT,y) +$(call force,CFG_MAP_EXT_DT_SECURE,y) +endif + # Maximum size of the Device Tree Blob, has to be large enough to allow # editing of the supplied DTB. CFG_DTB_MAX_SIZE ?= 0x10000 @@ -543,6 +558,10 @@ CFG_DRIVERS_CLK_EARLY_PROBE ?= n $(call force,CFG_DRIVERS_DT_RECURSIVE_PROBE,n,Mandated by CFG_DT_DRIVER_EMBEDDED_TEST) endif +# CFG_WITH_STATS when enabled embeds PTA statistics service to allow non-secure +# clients to retrieve debug and statistics information on core and loaded TAs. +CFG_WITH_STATS ?= n + # CFG_DRIVERS_DT_RECURSIVE_PROBE when enabled forces a recursive subnode # parsing in the embedded DTB for driver probing. The alternative is # an exploration based on compatible drivers found. It is default disabled. @@ -715,9 +734,20 @@ CFG_CRYPTOLIB_DIR ?= core/lib/libtomcrypt # that would set = n. $(call force,CFG_CORE_MBEDTLS_MPI,y) -# Enable virtualization support. OP-TEE will not work without compatible -# hypervisor if this option is enabled. +# When enabled, CFG_NS_VIRTUALIZATION embeds support for virtualization in +# the non-secure world. OP-TEE will not work without a compatible hypervisor +# in the non-secure world if this option is enabled. +# +# CFG_VIRTUALIZATION served the same purpose as CFG_NS_VIRTUALIZATION but is +# deprecated as the configuration switch name was ambiguous regarding which +# world has virtualization enabled. +ifneq (undefined,$(flavor CFG_VIRTUALIZATION)) +$(info WARNING: CFG_VIRTUALIZATION is deprecated, use CFG_NS_VIRTUALIZATION instead) CFG_NS_VIRTUALIZATION ?= $(CFG_VIRTUALIZATION) +ifneq ($(CFG_NS_VIRTUALIZATION),$(CFG_VIRTUALIZATION)) +$(error Inconsistent CFG_NS_VIRTUALIZATION=$(CFG_NS_VIRTUALIZATION) and CFG_VIRTUALIZATION=$(CFG_VIRTUALIZATION)) +endif +endif # CFG_VIRTUALIZATION defined CFG_NS_VIRTUALIZATION ?= n ifeq ($(CFG_NS_VIRTUALIZATION),y) @@ -859,10 +889,13 @@ CFG_PREALLOC_RPC_CACHE ?= y # CFG_DRIVERS_CLK_DT embeds devicetree clock parsing support # CFG_DRIVERS_CLK_FIXED add support for "fixed-clock" compatible clocks # CFG_DRIVERS_CLK_EARLY_PROBE makes clocks probed at early_init initcall level. +# CFG_DRIVERS_CLK_PRINT_TREE embeds a helper function to print the clock tree +# state on OP-TEE core console with the debug trace level. CFG_DRIVERS_CLK ?= n CFG_DRIVERS_CLK_DT ?= $(call cfg-all-enabled,CFG_DRIVERS_CLK CFG_DT) CFG_DRIVERS_CLK_FIXED ?= $(CFG_DRIVERS_CLK_DT) CFG_DRIVERS_CLK_EARLY_PROBE ?= $(CFG_DRIVERS_CLK_DT) +CFG_DRIVERS_CLK_PRINT_TREE ?= n $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_DT,CFG_DRIVERS_CLK CFG_DT)) $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_FIXED,CFG_DRIVERS_CLK_DT)) @@ -878,6 +911,10 @@ CFG_DRIVERS_GPIO ?= n # When enabled, CFG_DRIVERS_I2C provides I2C controller and devices support. CFG_DRIVERS_I2C ?= n +# When enabled, CFG_DRIVERS_NVMEM provides a framework to register nvmem +# providers and allow consumer drivers to get NVMEM cells using the Device Tree. +CFG_DRIVERS_NVMEM ?= n + # When enabled, CFG_DRIVERS_PINCTRL embeds a pin muxing controller framework in # OP-TEE core to provide drivers a way to apply pin muxing configurations based #Â on device-tree. @@ -889,21 +926,42 @@ CFG_DRIVERS_PINCTRL ?= n # # When enabled, CFG_REGULATOR_FIXED embeds a voltage regulator driver for # DT compatible "regulator-fixed" devices. +# +# When enabled, CFG_REGULATOR_GPIO embeds a voltage regulator driver for +# DT compatible "regulator-gpio" devices. +# +# CFG_DRIVERS_REGULATOR_PRINT_TREE embeds a helper function to print the +# regulator tree state on OP-TEE core console with the info trace level. CFG_DRIVERS_REGULATOR ?= n +CFG_DRIVERS_REGULATOR_PRINT_TREE ?= n CFG_REGULATOR_FIXED ?= n +CFG_REGULATOR_GPIO ?= n $(eval $(call cfg-enable-all-depends,CFG_REGULATOR_FIXED, \ CFG_DRIVERS_REGULATOR CFG_DT)) +$(eval $(call cfg-enable-all-depends,CFG_REGULATOR_GPIO, \ + CFG_DRIVERS_REGULATOR CFG_DT CFG_DRIVERS_GPIO)) -# The purpose of this flag is to show a print when booting up the device that -# indicates whether the board runs a standard developer configuration or not. -# A developer configuration doesn't necessarily has to be secure. The intention +# When enabled, CFG_INSECURE permits insecure configuration of OP-TEE core +# and shows a print (info level) when booting up the device that +# indicates that the board runs a standard developer configuration. +# +# A developer configuration doesn't necessarily have to be secure. The intention # is that the one making products based on OP-TEE should override this flag in # plat-xxx/conf.mk for the platform they're basing their products on after # they've finalized implementing stubbed functionality (see OP-TEE # documentation/Porting guidelines) as well as vendor specific security # configuration. -CFG_WARN_INSECURE ?= y +# +# CFG_WARN_INSECURE served the same purpose as CFG_INSECURE but is deprecated. +ifneq (undefined,$(flavor CFG_WARN_INSECURE)) +$(info WARNING: CFG_WARN_INSECURE is deprecated, use CFG_INSECURE instead) +CFG_INSECURE ?= $(CFG_WARN_INSECURE) +ifneq ($(CFG_INSECURE),$(CFG_WARN_INSECURE)) +$(error Inconsistent CFG_INSECURE=$(CFG_INSECURE) and CFG_WARN_INSECURE=$(CFG_WARN_INSECURE)) +endif +endif # CFG_WARN_INSECURE defined +CFG_INSECURE ?= y # Enables warnings for declarations mixed with statements CFG_WARN_DECL_AFTER_STATEMENT ?= y @@ -951,11 +1009,19 @@ CFG_PAN ?= n $(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core)) +ifeq ($(filter y, $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \ + $(CFG_CORE_EL3_SPMC)),y) +# FF-A case, handled via the FF-A ABI +CFG_CORE_ASYNC_NOTIF ?= y +$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,n) +else # CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support -# for sending asynchronous notifications to normal world. Note that an -# interrupt ID must be configurged by the platform too. Currently is only +# for sending asynchronous notifications to normal world. +# Interrupt ID must be configurged by the platform too. Currently is only # CFG_CORE_ASYNC_NOTIF_GIC_INTID defined. CFG_CORE_ASYNC_NOTIF ?= n +$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,$(CFG_CORE_ASYNC_NOTIF)) +endif $(eval $(call cfg-enable-all-depends,CFG_MEMPOOL_REPORT_LAST_OFFSET, \ CFG_WITH_STATS)) @@ -1063,3 +1129,23 @@ CFG_HMAC_64_1024_RANGE ?= n # By default use standard pbkdf2 implementation CFG_CRYPTO_HW_PBKDF2 ?= n $(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2)) + +# CFG_HALT_CORES_ON_PANIC, when enabled, makes any call to panic() halt the +# other cores. The feature currently relies on GIC device to trap the other +# cores using an SGI interrupt specified by CFG_HALT_CORES_ON_PANIC_SGI. +CFG_HALT_CORES_ON_PANIC ?= n +CFG_HALT_CORES_ON_PANIC_SGI ?= 15 +$(eval $(call cfg-depends-all,CFG_HALT_CORES_ON_PANIC,CFG_GIC)) + +# Enable automatic discovery of maximal PA supported by the hardware and +# use that. Provides easier configuration of virtual platforms where the +# maximal PA can vary. +CFG_AUTO_MAX_PA_BITS ?= n + +# CFG_DRIVERS_REMOTEPROC, when enabled, embeds support for remote processor +# management including generic DT bindings for the configuration. +CFG_DRIVERS_REMOTEPROC ?= n + +# CFG_REMOTEPROC_PTA, when enabled, embeds remote processor management PTA +# service. +CFG_REMOTEPROC_PTA ?= n \ No newline at end of file diff --git a/scripts/checkpatch_inc.sh b/scripts/checkpatch_inc.sh index fb77d5ca2f9520e85dfdfeee972e2114aca54d25..166774af53a59d42861e65033424fe77894d5494 100644 --- a/scripts/checkpatch_inc.sh +++ b/scripts/checkpatch_inc.sh @@ -23,7 +23,7 @@ function _checkpatch() { typedefs_opt=""; # Ignore NOT_UNIFIED_DIFF in case patch has no diff # (e.g., all paths filtered out) - $CHECKPATCH $CHECKPATCH_OPT $typedefs_opt - + eval "$CHECKPATCH $CHECKPATCH_OPT $typedefs_opt -" } function checkpatch() { diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py new file mode 100755 index 0000000000000000000000000000000000000000..1d2b49e91c19d943a29b72e5eb6539dc334a94ba --- /dev/null +++ b/scripts/gen_compile_commands.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2018 +# +# Author: Tom Roeder <tmroeder@google.com> +# Ported and modified for U-Boot by Joao Marcos Costa <jmcosta944@gmail.com> +# Briefly documented at doc/build/gen_compile_commands.rst +# +# Ported and modified for OP-TEE by Joakim Bech <joakim.bech@linaro.org> +"""A tool for generating compile_commands.json in OP-TEE.""" + +import argparse +import json +import logging +import os +import re +import subprocess +import sys + +_DEFAULT_OUTPUT = 'compile_commands.json' +_DEFAULT_LOG_LEVEL = 'WARNING' + +_FILENAME_PATTERN = r'^\..*\.cmd$' +_LINE_PATTERN = r'^old-cmd[^ ]* := (?:/usr/bin/ccache )?(.*) -c (\S+)' + +_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] +# The tools/ directory adopts a different build system, and produces .cmd +# files in a different format. Do not support it. +_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools'] + + +def parse_arguments(): + """Sets up and parses command-line arguments. + + Returns: + log_level: A logging level to filter log output. + directory: The work directory where the objects were built. + ar: Command used for parsing .a archives. + output: Where to write the compile-commands JSON file. + paths: The list of files/directories to handle to find .cmd files. + """ + usage = 'Creates a compile_commands.json database from OP-TEE .cmd files' + parser = argparse.ArgumentParser(description=usage) + + directory_help = ('specify the output directory used for the OP-TEE build ' + '(defaults to the working directory)') + parser.add_argument('-d', '--directory', type=str, default='.', + help=directory_help) + + output_help = ('path to the output command database (defaults to ' + + _DEFAULT_OUTPUT + ')') + parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, + help=output_help) + + log_level_help = ('the level of log messages to produce (defaults to ' + + _DEFAULT_LOG_LEVEL + ')') + parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, + default=_DEFAULT_LOG_LEVEL, help=log_level_help) + + ar_help = 'command used for parsing .a archives' + parser.add_argument('-a', '--ar', type=str, default='llvm-ar', + help=ar_help) + + paths_help = ('directories to search or files to parse ' + '(files should be *.o, *.a, or modules.order). ' + 'If nothing is specified, the current directory is searched') + parser.add_argument('paths', type=str, nargs='*', help=paths_help) + + args = parser.parse_args() + + return (args.log_level, + os.path.abspath(args.directory), + args.output, + args.ar, + args.paths if len(args.paths) > 0 else [args.directory]) + + +def cmdfiles_in_dir(directory): + """Generate the iterator of .cmd files found under the directory. + + Walk under the given directory, and yield every .cmd file found. + + Args: + directory: The directory to search for .cmd files. + + Yields: + The path to a .cmd file. + """ + + filename_matcher = re.compile(_FILENAME_PATTERN) + exclude_dirs = [os.path.join(directory, d) for d in _EXCLUDE_DIRS] + + for dirpath, dirnames, filenames in os.walk(directory, topdown=True): + # Prune unwanted directories. + if dirpath in exclude_dirs: + dirnames[:] = [] + continue + + for filename in filenames: + if filename_matcher.match(filename): + yield os.path.join(dirpath, filename) + + +def to_cmdfile(path): + """Return the path of .cmd file used for the given build artifact + + Args: + Path: file path + + Returns: + The path to .cmd file + """ + dir, base = os.path.split(path) + return os.path.join(dir, '.' + base + '.cmd') + + +def cmdfiles_for_a(archive, ar): + """Generate the iterator of .cmd files associated with the archive. + + Parse the given archive, and yield every .cmd file used to build it. + + Args: + archive: The archive to parse + + Yields: + The path to every .cmd file found + """ + for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): + yield to_cmdfile(obj) + + +def cmdfiles_for_modorder(modorder): + """Generate the iterator of .cmd files associated with the modules.order. + + Parse the given modules.order, and yield every .cmd file used to build the + contained modules. + + Args: + modorder: The modules.order file to parse + + Yields: + The path to every .cmd file found + """ + with open(modorder) as f: + for line in f: + obj = line.rstrip() + base, ext = os.path.splitext(obj) + if ext != '.o': + sys.exit('{}: module path must end with .o'.format(obj)) + mod = base + '.mod' + # Read from *.mod, to get a list of objects that compose the + # module. + with open(mod) as m: + for mod_line in m: + yield to_cmdfile(mod_line.rstrip()) + + +def process_line(root_directory, command_prefix, file_path): + """Extracts information from a .cmd line and creates an entry from it. + + Args: + root_directory: The directory that was searched for .cmd files. Usually + used directly in the "directory" entry in compile_commands.json. + command_prefix: The extracted command line, up to the last element. + file_path: The .c file from the end of the extracted command. + Usually relative to root_directory, but sometimes absolute. + + Returns: + An entry to append to compile_commands. + + Raises: + ValueError: Could not find the extracted file based on file_path and + root_directory or file_directory. + """ + # The .cmd files are intended to be included directly by Make, so they + # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the + # kernel version). The compile_commands.json file is not interpreted + # by Make, so this code replaces the escaped version with '#'. + prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#') # noqa: W605 + + # Use os.path.abspath() to normalize the path resolving '.' and '..' . + abs_path = os.path.abspath(os.path.join(root_directory, file_path)) + if not os.path.exists(abs_path): + raise ValueError('File %s not found' % abs_path) + return { + 'directory': root_directory, + 'file': abs_path, + 'command': prefix + file_path, + } + + +def main(): + """Walks through the directory and finds and parses .cmd files.""" + log_level, directory, output, ar, paths = parse_arguments() + + level = getattr(logging, log_level) + logging.basicConfig(format='%(levelname)s: %(message)s', level=level) + + line_matcher = re.compile(_LINE_PATTERN) + + compile_commands = [] + + for path in paths: + # If 'path' is a directory, handle all .cmd files under it. + # Otherwise, handle .cmd files associated with the file. + # built-in objects are linked via vmlinux.a + # Modules are listed in modules.order. + if os.path.isdir(path): + cmdfiles = cmdfiles_in_dir(path) + elif path.endswith('.a'): + cmdfiles = cmdfiles_for_a(path, ar) + elif path.endswith('modules.order'): + cmdfiles = cmdfiles_for_modorder(path) + else: + sys.exit('{}: unknown file type'.format(path)) + + for cmdfile in cmdfiles: + with open(cmdfile, 'rt') as f: + try: + result = line_matcher.match(f.readline()) + if result: + entry = process_line(directory, result.group(1), + result.group(2)) + compile_commands.append(entry) + except ValueError as err: + logging.info('Could not add line from %s: %s', + cmdfile, err) + except AttributeError as err: + continue + + with open(output, 'wt') as f: + json.dump(compile_commands, f, indent=2, sort_keys=True) + + +if __name__ == '__main__': + main() diff --git a/scripts/symbolize.py b/scripts/symbolize.py index 2a7843433d5dc7402f1d3a5ac3b74291b510c8c1..87b2466034fabf7cd01de0e349256fe083f7ddbc 100755 --- a/scripts/symbolize.py +++ b/scripts/symbolize.py @@ -19,7 +19,7 @@ TEE_LOAD_ADDR_RE = re.compile(r'TEE load address @ (?P<load_addr>0x[0-9a-f]+)') # This gets the address from lines looking like this: # E/TC:0 0x001044a8 STACK_ADDR_RE = re.compile( - r'[UEIDFM]/(TC|LD):(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)') + r'[UEIDFM]/(TC|LD):([0-9]+ )?(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)') ABORT_ADDR_RE = re.compile(r'-abort at address (?P<addr>0x[0-9a-f]+)') TA_PANIC_RE = re.compile(r'TA panicked with code (?P<code>0x[0-9a-f]+)') REGION_RE = re.compile(r'region +[0-9]+: va (?P<addr>0x[0-9a-f]+) ' diff --git a/ta/pkcs11/src/object.c b/ta/pkcs11/src/object.c index 053237bc346a12256f6a0095077cd0e520818263..bbd2b682288f4f3932aab9825bea80b25db169ac 100644 --- a/ta/pkcs11/src/object.c +++ b/ta/pkcs11/src/object.c @@ -352,6 +352,11 @@ enum pkcs11_rc entry_create_object(struct pkcs11_client *client, if (rc) goto out; + /* Set key check value attribute */ + rc = set_check_value_attr(&head); + if (rc) + goto out; + /* * Check target object attributes match target processing * Check target object attributes match token state @@ -983,6 +988,8 @@ enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, size_t template_size = 0; struct pkcs11_object *obj = NULL; struct obj_attrs *head = NULL; + struct obj_attrs *head_new = NULL; + struct obj_attrs *head_old = NULL; uint32_t object_handle = 0; enum processing_func function = PKCS11_FUNCTION_MODIFY; @@ -1056,25 +1063,50 @@ enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, if (rc) goto out; + /* Create new object attributes to modify */ + template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; + head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); + if (!head_new) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_MemMove(head_new, obj->attributes, template_size); + /* * All checks complete. The attributes in @head have been checked and * can now be used to set/modify the object attributes. */ - rc = modify_attributes_list(&obj->attributes, head); + rc = modify_attributes_list(&head_new, head); + if (rc) + goto out; + + /* Set key check value attribute */ + rc = set_check_value_attr(&head_new); if (rc) goto out; + /* Update the object */ + head_old = obj->attributes; + obj->attributes = head_new; + head_new = NULL; + if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { rc = update_persistent_object_attributes(obj); - if (rc) + if (rc) { + obj->attributes = head_old; goto out; + } } + TEE_Free(head_old); + DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, session->handle, object_handle); out: TEE_Free(head); + TEE_Free(head_new); TEE_Free(template); return rc; } @@ -1216,6 +1248,11 @@ enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, if (rc) goto out; + /* Set key check value attribute */ + rc = set_check_value_attr(&head_new); + if (rc) + goto out; + /* * At this stage the object is almost created: all its attributes are * referenced in @head_new, including the key value and are assumed diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c index aef712ee55bc323d94e3640d827ff357a829336c..c0e9d7c51e9f8063dea982f6cff3261a4df4c739 100644 --- a/ta/pkcs11/src/pkcs11_attributes.c +++ b/ta/pkcs11/src/pkcs11_attributes.c @@ -4,6 +4,7 @@ */ #include <assert.h> +#include <config.h> #include <inttypes.h> #include <mbedtls/asn1write.h> #include <mbedtls/ecp.h> @@ -355,8 +356,12 @@ static const uint32_t pkcs11_certificate_boolprops[] = { }; static const uint32_t pkcs11_certificate_optional[] = { - PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_CHECK_VALUE, - PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO, + PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_START_DATE, + PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO, +#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE + /* Consider KCV attribute only when supported */ + PKCS11_CKA_CHECK_VALUE, +#endif }; /* @@ -404,6 +409,10 @@ static const uint32_t symm_key_opt_or_null[] = { static const uint32_t symm_key_optional[] = { PKCS11_CKA_VALUE_LEN, +#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE + /* Consider KCV attribute only when supported */ + PKCS11_CKA_CHECK_VALUE, +#endif }; /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */ @@ -2173,6 +2182,7 @@ static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr, case PKCS11_CKA_VERIFY: case PKCS11_CKA_WRAP: case PKCS11_CKA_UNWRAP: + case PKCS11_CKA_CHECK_VALUE: return true; /* Can't be modified once set to CK_FALSE - 12 in Table 10 */ case PKCS11_CKA_EXTRACTABLE: @@ -2478,7 +2488,11 @@ static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data, if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_GENERAL_ERROR; - return add_attribute(head, PKCS11_CKA_VALUE, data, key_length); + rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length); + if (rc) + return rc; + + return set_check_value_attr(head); } static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head, @@ -2827,3 +2841,188 @@ enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, else return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size); } + +/* + * The key check value is derived from the object by taking the first + * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute. + */ +static enum pkcs11_rc compute_check_value_with_sha1(void *key, + uint32_t key_size, + void *kcv) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + size_t buf_size = TEE_MAX_HASH_SIZE; + uint8_t *buf = NULL; + + assert(key && kcv); + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO); + if (!buf) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); + +out: + TEE_Free(buf); + TEE_FreeOperation(op); + + return rc; +} + +/* + * The key check value that is calculated as follows: + * 1) Take a buffer of the cipher block size of binary zeros (0x00). + * 2) Encrypt this block in ECB mode. + * 3) Take the first three bytes of cipher text as the check value. + */ +static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size, + void *kcv) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle hkey = TEE_HANDLE_NULL; + TEE_Attribute attr = { }; + uint8_t buf[TEE_AES_BLOCK_SIZE] = { }; + size_t buf_size = sizeof(buf); + + assert(key && kcv); + + res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD, + TEE_MODE_ENCRYPT, key_size * 8); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size); + + res = TEE_PopulateTransientObject(hkey, &attr, 1); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + res = TEE_SetOperationKey(op, hkey); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_CipherInit(op, NULL, 0); + + res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); + +out: + TEE_FreeTransientObject(hkey); + TEE_FreeOperation(op); + + return rc; +} + +enum pkcs11_rc set_check_value_attr(struct obj_attrs **head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t val_len = 0; + uint32_t kcv2_len = 0; + void *val = NULL; + uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { }; + void *kcv2 = NULL; + + assert(head && *head); + + if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE)) + return PKCS11_CKR_OK; + + switch (get_class(*head)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_CERTIFICATE: + break; + default: + /* Nothing to do */ + return PKCS11_CKR_OK; + } + + /* Check whether CKA_CHECK_VALUE has been provided in the template */ + rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len); + + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_GENERAL_ERROR; + + /* + * The generation of the KCV may be prevented by the application + * supplying the attribute in the template as a no-value (0 length) + * entry. + */ + if (rc == PKCS11_CKR_OK && !kcv2_len) + return PKCS11_CKR_OK; + + if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE) + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + + /* Get key CKA_VALUE */ + rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len); + if (rc) + return rc; + + if (get_class(*head) == PKCS11_CKO_SECRET_KEY) { + switch (get_key_type(*head)) { + case PKCS11_CKK_AES: + rc = compute_check_value_with_ecb(val, val_len, kcv); + break; + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + case PKCS11_CKK_SHA224_HMAC: + rc = compute_check_value_with_sha1(val, val_len, kcv); + break; + default: + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + break; + } + } else { + rc = compute_check_value_with_sha1(val, val_len, kcv); + } + + if (rc) + return rc; + + /* + * If the computed KCV does not match the provided one + * then return CKR_ATTRIBUTE_VALUE_INVALID + */ + if (kcv2_len) { + /* Provided KCV value shall match the computed one */ + if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE)) + rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } else { + rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv, + PKCS11_CKA_CHECK_VALUE_SIZE); + } + + return rc; +} diff --git a/ta/pkcs11/src/pkcs11_attributes.h b/ta/pkcs11/src/pkcs11_attributes.h index 1834b430db4ca0dd916f696c4b3dc16865649d74..60cff66e731a056eb3a523f5a66498b93493dc5d 100644 --- a/ta/pkcs11/src/pkcs11_attributes.h +++ b/ta/pkcs11/src/pkcs11_attributes.h @@ -11,6 +11,9 @@ #include "serializer.h" +/* The key check value (KCV) attribute for objects is 3 bytes */ +#define PKCS11_CKA_CHECK_VALUE_SIZE U(3) + struct obj_attrs; struct pkcs11_object; struct pkcs11_session; @@ -214,5 +217,11 @@ enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data, */ enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, struct obj_attrs **priv_head); +/* + * Check an object's check value (Checksum) + * @head: Object attribute where to find KCV to be checked + * Return a pkcs11_rv compliant value + */ +enum pkcs11_rc set_check_value_attr(struct obj_attrs **head); #endif /*PKCS11_TA_PKCS11_ATTRIBUTES_H*/ diff --git a/ta/pkcs11/src/pkcs11_token.c b/ta/pkcs11/src/pkcs11_token.c index ab0fc291ef4ba17e4fe23412037755a6f1fdc947..2633b369723b495991193fcd338171b2248ebc6a 100644 --- a/ta/pkcs11/src/pkcs11_token.c +++ b/ta/pkcs11/src/pkcs11_token.c @@ -1132,117 +1132,117 @@ static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, uint8_t *pin, size_t pin_size) { struct ck_token *token = session->token; + struct token_persistent_main *db = token->db_main; enum pkcs11_rc rc = PKCS11_CKR_OK; - assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); + assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED); if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && - token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) return verify_identity_auth(token, PKCS11_CKU_SO); - if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) + if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; - rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, - token->db_main->so_pin_salt, - token->db_main->so_pin_hash); - if (rc) { - unsigned int pin_count = 0; - - if (rc != PKCS11_CKR_PIN_INCORRECT) - return rc; - - token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; - token->db_main->so_pin_count++; + /* + * Preset the counter and flags conservatively in the database so that + * the tentative is saved whatever happens next. + */ + db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; + db->so_pin_count++; - pin_count = token->db_main->so_pin_count; - if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) - token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; - if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) - token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; + if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) + db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; + else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) + db->flags |= PKCS11_CKFT_SO_PIN_LOCKED; - update_persistent_db(token); + update_persistent_db(token); - if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) + rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, + db->so_pin_salt, + db->so_pin_hash); + if (rc == PKCS11_CKR_PIN_INCORRECT) { + if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; return PKCS11_CKR_PIN_INCORRECT; } - if (token->db_main->so_pin_count) { - token->db_main->so_pin_count = 0; + if (rc) + db->so_pin_count--; + else + db->so_pin_count = 0; - update_persistent_db(token); + db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED; + if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) { + db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY; + if (!db->so_pin_count) + db->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW; } - if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW | - PKCS11_CKFT_SO_PIN_FINAL_TRY)) { - token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | - PKCS11_CKFT_SO_PIN_FINAL_TRY); - - update_persistent_db(token); - } + update_persistent_db(token); - return PKCS11_CKR_OK; + return rc; } static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, uint8_t *pin, size_t pin_size) { struct ck_token *token = session->token; + struct token_persistent_main *db = token->db_main; enum pkcs11_rc rc = PKCS11_CKR_OK; + if (!(db->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) + return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && - token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) return verify_identity_auth(token, PKCS11_CKU_USER); - if (!token->db_main->user_pin_salt) - return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; + assert(db->user_pin_salt); - if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) + if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; - rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, - token->db_main->user_pin_salt, - token->db_main->user_pin_hash); - if (rc) { - unsigned int pin_count = 0; - - if (rc != PKCS11_CKR_PIN_INCORRECT) - return rc; - - token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; - token->db_main->user_pin_count++; + /* + * Preset the counter and flags conservatively in the database so that + * the tentative is saved whatever happens next. + */ + db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; + db->user_pin_count++; - pin_count = token->db_main->user_pin_count; - if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) - token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; - if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) - token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED; + if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) + db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; + else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) + db->flags |= PKCS11_CKFT_USER_PIN_LOCKED; - update_persistent_db(token); + update_persistent_db(token); - if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) + rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, + db->user_pin_salt, + db->user_pin_hash); + if (rc == PKCS11_CKR_PIN_INCORRECT) { + if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; return PKCS11_CKR_PIN_INCORRECT; } - if (token->db_main->user_pin_count) { - token->db_main->user_pin_count = 0; + if (rc) + db->user_pin_count--; + else + db->user_pin_count = 0; - update_persistent_db(token); + db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED; + if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) { + db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY; + if (!db->user_pin_count) + db->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW; } - if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW | - PKCS11_CKFT_USER_PIN_FINAL_TRY)) { - token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW | - PKCS11_CKFT_USER_PIN_FINAL_TRY); - - update_persistent_db(token); - } + update_persistent_db(token); - return PKCS11_CKR_OK; + return rc; } enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, diff --git a/ta/pkcs11/src/processing.c b/ta/pkcs11/src/processing.c index 6be34829db24d4e0b61c15e00fdcfc15702b0552..0fc26b37597b0c4936cada804b84ee8eb0d8bef2 100644 --- a/ta/pkcs11/src/processing.c +++ b/ta/pkcs11/src/processing.c @@ -166,10 +166,10 @@ size_t get_object_key_bit_size(struct pkcs11_object *obj) static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; - void *data = NULL; uint32_t data_size = 0; uint32_t value_len = 0; void *value = NULL; + void *data = NULL; if (!*head) return PKCS11_CKR_TEMPLATE_INCONSISTENT; @@ -196,6 +196,9 @@ static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); + if (rc == PKCS11_CKR_OK) + rc = set_check_value_attr(head); + TEE_Free(value); return rc; diff --git a/ta/pkcs11/sub.mk b/ta/pkcs11/sub.mk index 30dd13cb53395b56d214a93aa2233821f181d79b..aa66ee0ef0429c3f54412fd9b71fb5ee49282d42 100644 --- a/ta/pkcs11/sub.mk +++ b/ta/pkcs11/sub.mk @@ -10,6 +10,9 @@ CFG_PKCS11_TA_HEAP_SIZE ?= (32 * 1024) # Defines the number of PKCS11 token implemented by the PKCS11 TA CFG_PKCS11_TA_TOKEN_COUNT ?= 3 +# When enabled, embed support for object checksum value computation +CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y + global-incdirs-y += include global-incdirs-y += src subdirs-y += src diff --git a/ta/remoteproc/Makefile b/ta/remoteproc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0d1a5010ca58cdaff2406360fdc1c8da28ac9fbe --- /dev/null +++ b/ta/remoteproc/Makefile @@ -0,0 +1,18 @@ +# The UUID for the Trusted Application +BINARY=80a4c275-0a47-4905-8285-1486a9771a08 + +ifdef TA_CROSS_COMPILE +CROSS_COMPILE ?= $(TA_CROSS_COMPILE) +endif +export CROSS_COMPILE + +CFG_TEE_TA_LOG_LEVEL ?= 2 +CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) + +-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), ) +clean: + @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA' + @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)' +endif diff --git a/ta/remoteproc/include/ta_remoteproc.h b/ta/remoteproc/include/ta_remoteproc.h new file mode 100644 index 0000000000000000000000000000000000000000..71a15451568eef0f30fa9710700b2fa462393882 --- /dev/null +++ b/ta/remoteproc/include/ta_remoteproc.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef TA_REMOTEPROC_H +#define TA_REMOTEPROC_H + +/* + * This UUID is generated with uuidgen + * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html + */ +#define TA_REMOTEPROC_UUID { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* The command IDs implemented in this TA */ + +/* + * Authentication of the firmware and load in the remote processor memory. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: buffer containing the image of the firmware + */ +#define TA_RPROC_CMD_LOAD_FW 1 + +/* + * Start the remote processor. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define TA_RPROC_CMD_START_FW 2 + +/* + * Stop the remote processor. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define TA_RPROC_CMD_STOP_FW 3 + +/* + * Return the physical address of the resource table, or 0 if not found + * No check is done to verify that the address returned is accessible by the + * non-secure world. If the resource table is loaded in a protected memory, + * then accesses from non-secure world will likely fail. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].value.a: 32bit LSB resource table memory address + * [out] params[1].value.b: 32bit MSB resource table memory address + * [out] params[2].value.a: 32bit LSB resource table memory size + * [out] params[2].value.b: 32bit MSB resource table memory size + */ +#define TA_RPROC_CMD_GET_RSC_TABLE 4 + +/* + * Get remote processor firmware core dump. If found, return either + * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output + * buffer is too short to store the core dump. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].memref: Core dump, if found + */ +#define TA_RPROC_CMD_GET_COREDUMP 5 + +#endif /*TA_REMOTEPROC_H*/ diff --git a/ta/remoteproc/src/elf_parser.c b/ta/remoteproc/src/elf_parser.c new file mode 100644 index 0000000000000000000000000000000000000000..0cd0bc67d8c187551328d6dffe1fd6c5ba5a1f21 --- /dev/null +++ b/ta/remoteproc/src/elf_parser.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#include <assert.h> +#include <elf_parser.h> +#include <string.h> +#include <trace.h> +#include <types_ext.h> +#include <util.h> + +static bool va_in_fwm_image_range(void *va, uint8_t *fw, size_t fw_size) +{ + uint8_t *vaddr = va; + + return vaddr >= fw && vaddr < fw + fw_size; +} + +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + + if (!fw || !IS_ALIGNED_WITH_TYPE(fw, uint32_t)) { + EMSG("Invalid firmware address"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (size < sizeof(Elf32_Ehdr) || + size < (ehdr->e_shoff + sizeof(Elf32_Shdr))) + return TEE_ERROR_BAD_FORMAT; + + if (!IS_ELF(*ehdr) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) { + EMSG("Invalid header"); + return TEE_ERROR_BAD_FORMAT; + } + + if (ehdr->e_phnum == 0) { + EMSG("No loadable segment found"); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + Elf32_Phdr *phdr = (void *)((int8_t *)ehdr + ehdr->e_phoff); + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + if (!load_seg || fw + fw_size <= fw) + return TEE_ERROR_BAD_PARAMETERS; + + if (!IS_ALIGNED_WITH_TYPE(phdr, uint32_t) || + !va_in_fwm_image_range(phdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + uint32_t dst = phdr->p_paddr; + uint8_t *src = NULL; + + if (phdr->p_type != PT_LOAD) + continue; + + if (!va_in_fwm_image_range((void *)((vaddr_t)(phdr + 1) - 1), + fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + src = (uint8_t *)fw + phdr->p_offset; + + if (!va_in_fwm_image_range(src, fw, fw_size) || + !va_in_fwm_image_range(src + phdr->p_filesz, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + res = load_seg(src, phdr->p_filesz, dst, phdr->p_memsz, + priv_data); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, + Elf32_Addr *rsc_addr, + Elf32_Word *rsc_size) +{ + Elf32_Shdr *shdr = NULL; + unsigned int i = 0; + char *name_table = NULL; + struct resource_table *table = NULL; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + uint8_t *elf_data = fw; + + if (fw + fw_size <= fw || fw + ehdr->e_shoff < fw) + return TEE_ERROR_BAD_PARAMETERS; + + shdr = (void *)(fw + ehdr->e_shoff); + if (!IS_ALIGNED_WITH_TYPE(shdr, uint32_t) || + !va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + name_table = (char *)elf_data + shdr[ehdr->e_shstrndx].sh_offset; + if (!va_in_fwm_image_range(name_table, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + size_t size = shdr->sh_size; + size_t offset = shdr->sh_offset; + size_t s = 0; + + if (!va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + if (!shdr->sh_size) + return TEE_ERROR_NO_DATA; + + if (offset + size > fw_size || offset + size < size) { + EMSG("Resource table truncated"); + return TEE_ERROR_BAD_FORMAT; + } + + if (sizeof(struct resource_table) > size) { + EMSG("No header found in resource table"); + return TEE_ERROR_BAD_FORMAT; + } + + table = (struct resource_table *)(void *)(elf_data + offset); + if (!IS_ALIGNED_WITH_TYPE(table, uint32_t)) + return TEE_ERROR_CORRUPT_OBJECT; + + if (table->ver != 1) { + EMSG("Unsupported firmware version %"PRId32, + table->ver); + return TEE_ERROR_BAD_FORMAT; + } + + if (table->reserved[0] || table->reserved[1]) { + EMSG("Non zero reserved bytes"); + return TEE_ERROR_BAD_FORMAT; + } + + if (MUL_OVERFLOW(table->num, sizeof(*table->offset), &s) || + ADD_OVERFLOW(s, sizeof(struct resource_table), &s) || + s > size) { + EMSG("Resource table incomplete"); + return TEE_ERROR_BAD_FORMAT; + } + + DMSG("Resource table address %#"PRIx32", size %"PRIu32, + shdr->sh_addr, shdr->sh_size); + + *rsc_addr = shdr->sh_addr; + *rsc_size = shdr->sh_size; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} diff --git a/ta/remoteproc/src/elf_parser.h b/ta/remoteproc/src/elf_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..1bd658feb29ce516782b4554d4625fbbecd84639 --- /dev/null +++ b/ta/remoteproc/src/elf_parser.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef ELF_PARSER_H +#define ELF_PARSER_H + +#include <elf32.h> +#include <stdint.h> +#include <tee_api_types.h> + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * This structure shall be consistent with the Linux kernel structure + * definition from include/linux/remoteproc.h. + * + * The resource_table structure does not need to be packed in OP-TEE. The ELF + * parser does not access the system resources structures that follow this + * structure in shared memory (no memory alignment constraint on structures). + */ +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[]; +}; + +struct fw_elf32 { + uintptr_t e_entry; + uintptr_t e_phoff; + uintptr_t e_shoff; + uint32_t e_phnum; + uint32_t e_shnum; + uint32_t e_phentsize; + uint32_t e_shentsize; + + Elf32_Phdr *phdr; + Elf32_Shdr *shdr; +}; + +/* + * e32_parse_ehdr() - Check and parse the ELF header + * + * @fw: Firmware ELF file image + * @size: Byte size of firmware ELF file image + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size); + +/* + * e32_parser_load_elf_image() - simple ELF loader + * @fw: Firmware ELF file image + * @fw_size: Firmware ELF file image byte size + * @load_seg: Callback for loading a firmware image segment into device memory + * @priv_data: Private data passed to @load_seg callback. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data); + +/* + * e32_parser_find_rsc_table() - find resource table in an ELF image + * @fw: Firmware ELF file image + * @fw_size: Firmware ELF file image byte size + * @rsc_addr: Output resource table address from the remote proc perspective + * @rsc_size: Output resource table size + * Return TEE_SUCCESS if found, + * TEE_ERROR_NO_DATA if not found, + * or appropriate error. + */ +TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, + Elf32_Addr *rsc_addr, + Elf32_Word *rsc_size); + +#endif /*ELF_PARSER_H*/ diff --git a/ta/remoteproc/src/remoteproc_core.c b/ta/remoteproc/src/remoteproc_core.c new file mode 100644 index 0000000000000000000000000000000000000000..c3b815d9be1d0f6a4b63129069a02a5c3564b08e --- /dev/null +++ b/ta/remoteproc/src/remoteproc_core.c @@ -0,0 +1,1103 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#include <assert.h> +#include <elf_parser.h> +#include <remoteproc_pta.h> +#include <string.h> +#include <sys/queue.h> +#include <ta_remoteproc.h> +#include <tee_internal_api.h> +#include <tee_internal_api_extensions.h> +#include <types_ext.h> +#include <utee_defines.h> + +/* + * The remoteproc Trusted Application is in charge of authenticating and loading + * images signed by the scripts/sign_rproc_fw.py. The TA is also in charge of + * starting and stopping the remote processor. + * The structure of the signed image is: + * + * -----+-------------+ + * / | Magic | 32-bit word, magic value equal to + * / +-------------+ 0x3543A468 + * / +-------------+ + * / | version | 32-bit word, version of the format + * / +-------------+ + * +-----------+ +-------------+ + * | Header | | TLV size | 32-bit word, size of the TLV + * +-----------+ +-------------+ (aligned on 64-bit), in bytes. + * \ +-------------+ + * \ | sign size | 32-bit word, size of the signature + * \ +-------------+ (aligned on 64-bit), in bytes. + * \ +-------------+ + * \ | images size | 32-bit word, size of the images to + * -----+-------------+ load (aligned on 64-bit), in bytes. + * + * +-------------+ Information used to authenticate the + * | TLV | images and boot the remote processor, + * | | stored in Type-Length-Value format. + * +-------------+ 'Type' and 'Length' are 32-bit words. + * + * +-------------+ + * | Signature | Signature of the header and the TLV. + * +-------------+ + * + * +-------------+ + * | Firmware | + * | image 1 | + * +-------------+ + * ... + * +-------------+ + * | Firmware | + * | image n | + * +-------------+ + */ + +/* Firmware state */ +enum remoteproc_state { + REMOTEPROC_OFF = 0, + REMOTEPROC_LOADED, + REMOTEPROC_STARTED, +}; + +#define RPROC_HDR_MAGIC 0x3543A468 +#define HEADER_VERSION 1 + +/* Supported signature algorithm */ +enum remoteproc_sign_type { + RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1, + RPROC_ECDSA_SHA256 = 2, +}; + +enum remoteproc_img_type { + REMOTEPROC_ELF_TYPE = 1, + REMOTEPROC_INVALID_TYPE = 0xFF +}; + +/* remoteproc_tlv structure offsets */ +#define RPROC_TLV_LENGTH_OF U(0x04) +#define RPROC_TLV_VALUE_OF U(0x08) + +/* TLV types */ +#define RPROC_TLV_SIGNTYPE U(0x00000001) +#define RPROC_TLV_HASHTYPE U(0x00000002) +#define RPROC_TLV_NUM_IMG U(0x00000003) +#define RPROC_TLV_IMGTYPE U(0x00000004) +#define RPROC_TLV_IMGSIZE U(0x00000005) +#define RPROC_TLV_HASHTABLE U(0x00000010) +#define RPROC_TLV_PKEYINFO U(0x00000011) + +#define RPROC_PLAT_TLV_TYPE_MIN U(0x00010000) +#define RPROC_PLAT_TLV_TYPE_MAX U(0x00020000) + +#define RPROC_TLV_SIGNTYPE_LGTH U(1) + +#define ROUNDUP_64(x) ROUNDUP((x), sizeof(uint64_t)) + +/* + * struct remoteproc_tlv - Type-Length-Value structure + * @type: type of data + * @length: size of the data. + * @value: pointer to the data. + */ +struct remoteproc_tlv { + uint32_t type; + uint32_t length; + uint8_t value[]; +}; + +/* + * struct remoteproc_segment - program header with hash structure + * @phdr: program header + * @hash: hash associated to the program segment. + */ +struct remoteproc_segment { + Elf32_Phdr phdr; + uint8_t hash[TEE_SHA256_HASH_SIZE]; +}; + +/* + * struct remoteproc_fw_hdr - firmware header + * @magic: Magic number, must be equal to RPROC_HDR_MAGIC + * @version: Version of the header (must be 1) + * @tlv_len: Generic meta data chunk (TLV format) + * @sign_len: Signature chunk byte length + * @img_len: Firmware image chunk byte length + */ +struct remoteproc_fw_hdr { + uint32_t magic; + uint32_t version; + uint32_t tlv_len; + uint32_t sign_len; + uint32_t img_len; +}; + +#define FW_TLV_PTR(img, hdr) ((img) + sizeof(*(hdr))) +#define FW_SIGN_PTR(img, hdr) ({ \ + struct remoteproc_fw_hdr *__hdr = (hdr); \ + \ + FW_TLV_PTR((img), __hdr) + ROUNDUP_64(__hdr->tlv_len); \ + }) +#define FW_IMG_PTR(img, hdr) ({ \ + struct remoteproc_fw_hdr *___hdr = (hdr); \ + \ + FW_SIGN_PTR((img), ___hdr) + ROUNDUP_64(___hdr->sign_len); \ + }) + +/* + * struct remoteproc_sig_algo - signature algorithm information + * @sign_type: Header signature type + * @id: Signature algorithm identifier TEE_ALG_* + * @hash_len: Signature hash length + */ +struct remoteproc_sig_algo { + enum remoteproc_sign_type sign_type; + uint32_t id; + size_t hash_len; +}; + +/* + * struct remoteproc_context - firmware context + * @rproc_id: Unique Id of the processor + * @sec_cpy: Location of a secure copy of the header, TLVs and signature + * @tlvs: Location of a secure copy of the firmware TLVs + * @tlvs_sz: Byte size of the firmware TLVs blob. + * @fw_img: Firmware image + * @fw_img_sz: Byte size of the firmware image + * @hash_table: Location of a copy of the segment's hash table + * @nb_segment: number of segment to load + * @rsc_pa: Physical address of the firmware resource table + * @rsc_size: Byte size of the firmware resource table + * @state: Remote-processor state + * @hw_fmt: Image format capabilities of the remoteproc PTA + * @hw_img_prot: Image protection capabilities of the remoteproc PTA + * @link: Linked list element + */ +struct remoteproc_context { + uint32_t rproc_id; + uint8_t *sec_cpy; + uint8_t *tlvs; + size_t tlvs_sz; + uint8_t *fw_img; + size_t fw_img_sz; + struct remoteproc_segment *hash_table; + uint32_t nb_segment; + paddr_t rsc_pa; + size_t rsc_size; + enum remoteproc_state state; + uint32_t hw_fmt; + uint32_t hw_img_prot; + TAILQ_ENTRY(remoteproc_context) link; +}; + +TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context); + +static struct remoteproc_firmware_head firmware_head = + TAILQ_HEAD_INITIALIZER(firmware_head); + +static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = { + { + .sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256, + .id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, + { + .sign_type = RPROC_ECDSA_SHA256, + .id = TEE_ALG_ECDSA_P256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, +}; + +static size_t session_refcount; +static TEE_TASessionHandle pta_session; + +static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr) +{ + DMSG("magic :\t%#"PRIx32, hdr->magic); + DMSG("version :\t%#"PRIx32, hdr->version); + DMSG("tlv_len :\t%#"PRIx32, hdr->tlv_len); + DMSG("sign_len :\t%#"PRIx32, hdr->sign_len); + DMSG("img_len :\t%#"PRIx32, hdr->img_len); +} + +static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size, + uint16_t type, uint8_t **value, + size_t *length) +{ + uint8_t *p_tlv = (uint8_t *)tlv_chunk; + uint8_t *p_end_tlv = p_tlv + tlv_size; + uint32_t tlv_type = 0; + uint32_t tlv_length = 0; + uint32_t tlv_v = 0; + + *value = NULL; + *length = 0; + + /* Parse the TLV area */ + while (p_tlv < p_end_tlv) { + memcpy(&tlv_v, p_tlv, sizeof(tlv_v)); + tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v)); + tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + if (tlv_type == type) { + /* The specified TLV has been found */ + DMSG("TLV type %#"PRIx32" found, size %#"PRIx32, + type, tlv_length); + *value = &p_tlv[RPROC_TLV_VALUE_OF]; + *length = tlv_length; + if (tlv_length) + return TEE_SUCCESS; + else + return TEE_ERROR_NO_DATA; + } + p_tlv += ROUNDUP_64(sizeof(struct remoteproc_tlv) + tlv_length); + } + + return TEE_ERROR_NO_DATA; +} + +static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id) +{ + struct remoteproc_context *ctx = NULL; + + TAILQ_FOREACH(ctx, &firmware_head, link) + if (ctx->rproc_id == rproc_id) + return ctx; + + return NULL; +} + +static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id) +{ + struct remoteproc_context *ctx = NULL; + + ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO); + if (!ctx) + return NULL; + + ctx->rproc_id = rproc_id; + + TAILQ_INSERT_TAIL(&firmware_head, ctx, link); + + return ctx; +} + +static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type) +{ + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++) + if (sign_type == rproc_ta_sign_algo[i].sign_type) + return &rproc_ta_sign_algo[i]; + + return NULL; +} + +static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx, + const struct remoteproc_sig_algo *algo, + uint8_t *hash, uint32_t hash_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + struct rproc_pta_key_info *keyinfo = NULL; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + size_t length = 0; + uint8_t *tlv_keyinfo = NULL; + uint8_t *sign = NULL; + + res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, + RPROC_TLV_PKEYINFO, &tlv_keyinfo, + &length); + if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) + return res; + + keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO); + if (!keyinfo) + return TEE_ERROR_OUT_OF_MEMORY; + + keyinfo->algo = algo->id; + keyinfo->info_size = length; + memcpy(keyinfo->info, tlv_keyinfo, length); + + sign = FW_SIGN_PTR(ctx->sec_cpy, hdr); + + params[0].value.a = ctx->rproc_id; + params[1].memref.buffer = keyinfo; + params[1].memref.size = rproc_pta_keyinfo_size(keyinfo); + params[2].memref.buffer = hash; + params[2].memref.size = hash_len; + params[3].memref.buffer = sign; + params[3].memref.size = hdr->sign_len; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_VERIFY_DIGEST, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Failed to verify signature, res = %#"PRIx32, res); + + TEE_Free(keyinfo); + + return res; +} + +static TEE_Result +remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx, + void *fw_orig, uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = fw_orig; + uint32_t length = 0; + + if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr)) + return TEE_ERROR_BAD_PARAMETERS; + + if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) || + ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length)) + return TEE_ERROR_BAD_PARAMETERS; + + if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len) + return TEE_ERROR_BAD_PARAMETERS; + + remoteproc_header_dump(hdr); + + /* Copy the header, the TLVs and the signature in secure memory */ + ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); + if (!ctx->sec_cpy) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(ctx->sec_cpy, fw_orig, length); + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx) +{ + TEE_OperationHandle op = TEE_HANDLE_NULL; + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + const struct remoteproc_sig_algo *algo = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_sign_algo = NULL; + size_t length = 0; + uint8_t *hash = NULL; + size_t hash_len = 0; + + /* Get the algo type from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE, + &tlv_sign_algo, &length); + + if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH) + return TEE_ERROR_BAD_PARAMETERS; + + algo = remoteproc_get_algo(*tlv_sign_algo); + if (!algo) { + EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo); + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Compute the header and TLVs hashes */ + hash_len = algo->hash_len; + hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO); + if (!hash) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res != TEE_SUCCESS) + goto free_hash; + + TEE_DigestUpdate(op, hdr, sizeof(*hdr)); + res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len), + hash, &hash_len); + + if (res != TEE_SUCCESS) + goto out; + + /* + * This implementation could be enhanced by providing alternative to + * verify the signature in the TA. This could be done for instance by + * getting the key object from secure storage. + */ + + /* By default ask the remoteproc PTA to verify the signature. */ + res = remoteproc_pta_verify(ctx, algo, hash, hash_len); + +out: + TEE_FreeOperation(op); +free_hash: + TEE_Free(hash); + + return res; +} + +static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + uint32_t size = 0; + + if (hdr->magic != RPROC_HDR_MAGIC) + return TEE_ERROR_BAD_PARAMETERS; + + if (hdr->version != HEADER_VERSION) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * The offsets are aligned to 64 bits format. While the length of each + * chunks are the effective length, excluding the alignment padding + * bytes. + */ + if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) || + ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) || + ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) || + fw_orig_size != size) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + params[0].value.a = ctx->rproc_id; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_HW_CAPABILITIES, + param_types, params, NULL); + if (res) + return res; + + ctx->hw_fmt = params[1].value.a; + ctx->hw_img_prot = params[2].value.a; + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx, + uint8_t *fw_orig, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + res = get_rproc_pta_capabilities(ctx); + if (res) + return res; + + /* Secure the firmware image depending on strategy */ + if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) || + ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) { + /* + * Only hash table for ELF format support implemented + * in a first step. + */ + return TEE_ERROR_NOT_IMPLEMENTED; + } + + res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size); + if (res) + return res; + + res = remoteproc_verify_header(ctx, fw_orig_size); + if (res) + goto free_sec_cpy; + + hdr = (void *)ctx->sec_cpy; + ctx->tlvs_sz = hdr->tlv_len; + ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr); + + res = remoteproc_verify_signature(ctx); + if (res) + goto free_sec_cpy; + + /* Store location of the loadable binary in non-secure memory */ + ctx->fw_img_sz = hdr->img_len; + ctx->fw_img = FW_IMG_PTR(fw_orig, hdr); + + DMSG("Firmware images addr: %p size: %zu", ctx->fw_img, + ctx->fw_img_sz); + + return TEE_SUCCESS; + +free_sec_cpy: + TEE_Free(ctx->sec_cpy); + ctx->sec_cpy = NULL; + + return res; +} + +static paddr_t remoteproc_da_to_pa(uint32_t da, size_t size, + struct remoteproc_context *ctx) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + + /* + * The ELF file contains remote processor device addresses, that refer + * to the remote processor memory space. + * A translation is needed to get the corresponding physical address. + */ + + params[0].value.a = ctx->rproc_id; + params[1].value.a = da; + params[2].value.a = size; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_DA_TO_PA, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Failed to translate device address %#"PRIx32, da); + return 0; + } + + pa = (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a); + + /* Assert that the pa address is not 0 */ + assert(pa); + + return pa; +} + +static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx, + uint8_t *fw_img, size_t fw_img_sz, + paddr_t *rsc_pa, + size_t *rsc_size) +{ + uint32_t da = 0; + TEE_Result res = TEE_ERROR_GENERIC; + Elf32_Word size = 0; + + res = e32_parser_find_rsc_table(fw_img, fw_img_sz, &da, &size); + if (res) + return res; + + DMSG("Resource table device address %#"PRIx32" size %#"PRIx32, + da, size); + + *rsc_pa = remoteproc_da_to_pa(da, size, ctx); + if (!*rsc_pa) + return TEE_ERROR_ACCESS_DENIED; + + *rsc_size = size; + + return TEE_SUCCESS; +} + +static TEE_Result get_hash_table(struct remoteproc_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_hash = NULL; + struct remoteproc_segment *hash_table = NULL; + size_t length = 0; + + /* Get the segment's hash table from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE, + &tlv_hash, &length); + if (res) + return res; + + if (length % sizeof(struct remoteproc_segment)) + return TEE_ERROR_BAD_PARAMETERS; + + /* We can not ensure that tlv_hash is memory aligned so make a copy */ + hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); + if (!hash_table) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(hash_table, tlv_hash, length); + + ctx->hash_table = hash_table; + ctx->nb_segment = length / sizeof(struct remoteproc_segment); + + return TEE_SUCCESS; +} + +static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx, + uint8_t num_img, uint8_t idx, + uint8_t *img_type) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_value = NULL; + size_t length = 0; + + /* Get the type of the image to load, from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE, + &tlv_value, &length); + if (res) + return res; + + if (length != (sizeof(*img_type) * num_img)) + return TEE_ERROR_BAD_PARAMETERS; + + *img_type = tlv_value[idx]; + + return TEE_SUCCESS; +} + +static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx, + uint8_t num_img, uint8_t idx, + uint32_t *img_size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_value = NULL; + uint32_t tlv_v = 0; + size_t length = 0; + + /* Get the size of the image to load, from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE, + &tlv_value, &length); + if (res) + return res; + + if (length != (sizeof(*img_size) * num_img)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v)); + *img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + + return TEE_SUCCESS; +} + +static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src, + uint32_t size, uint32_t da, + uint32_t mem_size, uint8_t **hash) +{ + struct remoteproc_segment *peh = NULL; + unsigned int i = 0; + unsigned int nb_entry = ctx->nb_segment; + + peh = (void *)(ctx->hash_table); + + for (i = 0; i < nb_entry; peh++, i++) { + if (peh->phdr.p_paddr != da) + continue; + + /* + * Segment metadata are read from a non-secure memory. + * Validate them using hash table data stored in secure memory. + */ + if (peh->phdr.p_type != PT_LOAD) + return TEE_ERROR_BAD_PARAMETERS; + + if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (src < ctx->fw_img || + src > (ctx->fw_img + ctx->fw_img_sz) || + (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz)) + return TEE_ERROR_BAD_PARAMETERS; + + *hash = peh->hash; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} + +static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size, + uint32_t da, uint32_t mem_size, + void *priv) +{ + struct remoteproc_context *ctx = priv; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *hash = NULL; + + /* + * Invoke platform remoteproc PTA to load the segment in remote + * processor memory which is not mapped in the TA space. + */ + + DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size, + mem_size); + + res = get_segment_hash(ctx, src, size, da, mem_size, &hash); + if (res) + return res; + + params[0].value.a = ctx->rproc_id; + params[1].memref.buffer = src; + params[1].memref.size = size; + params[2].value.a = da; + params[3].memref.buffer = hash; + params[3].memref.size = TEE_SHA256_HASH_SIZE; + + if (size) { + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_LOAD_SEGMENT_SHA256, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Fails to load segment, res = 0x%#"PRIx32, res); + return res; + } + } + + /* Fill the rest of the memory with 0 */ + if (size < mem_size) { + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + params[1].value.a = da + size; + params[2].value.a = mem_size - size; + params[3].value.a = 0; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_SET_MEMORY, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Fails to clear segment, res = %#"PRIx32, res); + } + + return res; +} + +static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int num_img = 0; + unsigned int i = 0; + uint8_t img_type = REMOTEPROC_INVALID_TYPE; + uint32_t img_size = 0; + uint8_t *tlv = NULL; + int32_t offset = 0; + size_t length = 0; + paddr_t rsc_pa = 0; + size_t rsc_size = 0; + + res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz); + if (res) { + EMSG("Failed to parse firmware, res = %#"PRIx32, res); + return res; + } + + res = get_hash_table(ctx); + if (res) + return res; + + /* Get the number of firmware images to load */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG, + &tlv, &length); + if (res) + goto out; + if (length != sizeof(uint8_t)) { + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + num_img = *tlv; + if (!num_img) { + res = TEE_ERROR_NO_DATA; + goto out; + } + + /* + * Initialize resource table with zero. These values will be returned if + * no optional resource table is found in images. + */ + ctx->rsc_pa = 0; + ctx->rsc_size = 0; + + for (i = 0; i < num_img; i++) { + res = get_tlv_images_type(ctx, num_img, i, &img_type); + if (res) + goto out; + if (img_type != REMOTEPROC_ELF_TYPE) { + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + res = get_tlv_images_size(ctx, num_img, i, &img_size); + if (res) + goto out; + + res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size, + remoteproc_load_segment, ctx); + if (res) + goto out; + + /* Take opportunity to get the resource table address */ + res = remoteproc_parse_rsc_table(ctx, ctx->fw_img + offset, + img_size, &rsc_pa, &rsc_size); + if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) + goto out; + + if (res == TEE_SUCCESS) { + /* + * Only one resource table is supported, check that no + * other one has been declared in a previously loaded + * firmware. + */ + if (ctx->rsc_pa || ctx->rsc_size) { + EMSG("More than one resource table found"); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + ctx->rsc_pa = rsc_pa; + ctx->rsc_size = rsc_size; + } else { + /* + * No resource table found. Force to TEE_SUCCESS as the + * resource table is optional. + */ + res = TEE_SUCCESS; + } + offset += img_size; + } + +out: + /* Should we clean-up the memories in case of fail ? */ + TEE_Free(ctx->hash_table); + ctx->hash_table = NULL; + + return res; +} + +static TEE_Result remoteproc_load_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + ctx = remoteproc_add_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + if (ctx->state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + if (!params[1].memref.buffer || !params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + DMSG("Got base addr: %p size %#zx", params[1].memref.buffer, + params[1].memref.size); + + res = remoteproc_verify_firmware(ctx, params[1].memref.buffer, + params[1].memref.size); + if (res) { + EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res); + goto out; + } + + res = remoteproc_load_elf(ctx); + if (res) + goto out; + + ctx->state = REMOTEPROC_LOADED; + +out: + /* Clear reference to firmware image from shared memory */ + ctx->fw_img = NULL; + ctx->fw_img_sz = 0; + ctx->nb_segment = 0; + + /* Free allocated memories */ + TEE_Free(ctx->sec_cpy); + ctx->sec_cpy = NULL; + + return res; +} + +static TEE_Result remoteproc_start_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_OFF: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_STARTED: + res = TEE_SUCCESS; + break; + case REMOTEPROC_LOADED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_START, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_STARTED; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_stop_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_LOADED: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_OFF: + res = TEE_SUCCESS; + break; + case REMOTEPROC_STARTED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_STOP, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_OFF; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_get_rsc_table(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(params[0].value.a); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (ctx->state == REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + reg_pair_from_64((uint64_t)ctx->rsc_pa, + ¶ms[1].value.b, ¶ms[1].value.a); + reg_pair_from_64((uint64_t)ctx->rsc_size, + ¶ms[2].value.b, ¶ms[2].value.a); + + return TEE_SUCCESS; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +/* + * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor + * to manage. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + void **sess __unused) +{ + static const TEE_UUID uuid = PTA_RPROC_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!session_refcount) { + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params, + &pta_session, NULL); + if (res) + return res; + } + + session_refcount++; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *sess __unused) +{ + session_refcount--; + + if (!session_refcount) + TEE_CloseTASession(pta_session); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case TA_RPROC_CMD_LOAD_FW: + return remoteproc_load_fw(pt, params); + case TA_RPROC_CMD_START_FW: + return remoteproc_start_fw(pt, params); + case TA_RPROC_CMD_STOP_FW: + return remoteproc_stop_fw(pt, params); + case TA_RPROC_CMD_GET_RSC_TABLE: + return remoteproc_get_rsc_table(pt, params); + case TA_RPROC_CMD_GET_COREDUMP: + return TEE_ERROR_NOT_IMPLEMENTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/ta/remoteproc/src/sub.mk b/ta/remoteproc/src/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..81ba566acf9d1ff0e373fada527c37383615d586 --- /dev/null +++ b/ta/remoteproc/src/sub.mk @@ -0,0 +1,2 @@ +srcs-y += remoteproc_core.c +srcs-y += elf_parser.c diff --git a/ta/remoteproc/src/user_ta_header_defines.h b/ta/remoteproc/src/user_ta_header_defines.h new file mode 100644 index 0000000000000000000000000000000000000000..d303cb01bc304576b22cb4929b7b034a5ecfbfee --- /dev/null +++ b/ta/remoteproc/src/user_ta_header_defines.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023 STMicroelectronics + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include <ta_remoteproc.h> + +#define TA_UUID TA_REMOTEPROC_UUID + +#define TA_FLAGS (TA_FLAG_DEVICE_ENUM | \ + TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +/* Provisioned stack size */ +#define TA_STACK_SIZE (4 * 1024) + +/* Provisioned heap size for TEE_Malloc() and friends */ +#define TA_DATA_SIZE CFG_REMOTEPROC_TA_HEAP_SIZE + +/* The gpd.ta.version property */ +#define TA_VERSION "1.0" + +/* The gpd.ta.description property */ +#define TA_DESCRIPTION "remote processor firmware management" + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/ta/remoteproc/sub.mk b/ta/remoteproc/sub.mk new file mode 100644 index 0000000000000000000000000000000000000000..ae78d611bad4dba99cee461154a67025ce15b2a2 --- /dev/null +++ b/ta/remoteproc/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += src +subdirs-y += src diff --git a/ta/remoteproc/user_ta.mk b/ta/remoteproc/user_ta.mk new file mode 100644 index 0000000000000000000000000000000000000000..84721ff710b5d24868de9828e1506880a0455644 --- /dev/null +++ b/ta/remoteproc/user_ta.mk @@ -0,0 +1,4 @@ +user-ta-uuid := 80a4c275-0a47-4905-8285-1486a9771a08 + +# REMOTEPROC TA heap size can be customized if 4kB is not enough +CFG_REMOTEPROC_TA_HEAP_SIZE ?= (4 * 1024) diff --git a/ta/ta.mk b/ta/ta.mk index 09c20bfa16f5db4ad1562ce7b961f80a775f1f0a..ac46890c5dfc80a549698329f5209c8b3731b57f 100644 --- a/ta/ta.mk +++ b/ta/ta.mk @@ -190,7 +190,8 @@ $(foreach f, $(ta-keys), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/keys))) # Copy the scripts -ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py scripts/sign_rproc_fw.py +ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py \ + scripts/sign_rproc_fw.py scripts/ftrace_format.py $(foreach f, $(ta-scripts), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/scripts)))