qemu_v8: add support for Hafnium as S-EL2

Adds support for SPMC_AT_EL=2 where Hafnium is loaded at S-EL2 and
OP-TEE runs as an SP at S-EL1.

Hafnium requires both MTE and PAUTH support so make enable those
features in QEMU and TF-A as needed. The values $(MEMTAG) and $(PAUTH)
are not affected by the to allow independent configuration of OP-TEE
core.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
diff --git a/qemu_v8.mk b/qemu_v8.mk
index d244079..43e52f2 100644
--- a/qemu_v8.mk
+++ b/qemu_v8.mk
@@ -43,10 +43,10 @@
 # Option to configure FF-A and SPM:
 # n:	disabled
 # 3:	SPMC and SPMD at EL3 (in TF-A)
-# 2:	not supported, SPMC at S-EL2 (in Hafnium), SPMD at EL3 (in TF-A)
+# 2:	SPMC at S-EL2 (in Hafnium), SPMD at EL3 (in TF-A)
 # 1:	SPMC at S-EL1 (in OP-TEE), SPMD at EL3 (in TF-A)
 SPMC_AT_EL ?= n
-ifneq ($(filter-out n 1 3,$(SPMC_AT_EL)),)
+ifneq ($(filter-out n 1 2 3,$(SPMC_AT_EL)),)
 $(error Unsupported SPMC_AT_EL value $(SPMC_AT_EL))
 endif
 
@@ -76,6 +76,8 @@
 UBOOT_PATH		?= $(ROOT)/u-boot
 UBOOT_BIN		?= $(UBOOT_PATH)/u-boot.bin
 MKIMAGE_PATH		?= $(UBOOT_PATH)/tools
+HAFNIUM_PATH		?= $(ROOT)/hafnium
+HAFNIUM_BIN		?= $(HAFNIUM_PATH)/out/reference/secure_qemu_aarch64_clang/hafnium.bin
 
 ROOTFS_GZ		?= $(BINARIES_PATH)/rootfs.cpio.gz
 ROOTFS_UGZ		?= $(BINARIES_PATH)/rootfs.cpio.uboot
@@ -90,6 +92,12 @@
 ROOTFS_ENTRY		?= 0x44000000
 ROOTFS_LOADADDR		?= 0x44000000
 
+ifeq ($(SPMC_AT_EL),2)
+BL32_DEPS		?= hafnium optee-os
+else
+BL32_DEPS		?= optee-os
+endif
+
 ifeq ($(UBOOT),y)
 BL33_BIN		?= $(UBOOT_BIN)
 BL33_DEPS		?= u-boot
@@ -162,6 +170,7 @@
 	QEMU_USE_GIC_DRIVER=$(TFA_GIC_DRIVER) \
 	ENABLE_SVE_FOR_NS=1 \
 	ENABLE_SVE_FOR_SWD=1 \
+	ENABLE_FEAT_FGT=2 \
 	BL32_RAM_LOCATION=tdram \
 	DEBUG=$(TF_A_DEBUG) \
 	LOG_LEVEL=$(TF_A_LOGLVL)
@@ -176,6 +185,22 @@
 TF_A_FLAGS_SPMC_AT_EL_1 += ENABLE_SME_FOR_NS=0 ENABLE_SME_FOR_SWD=0
 TF_A_FLAGS_SPMC_AT_EL_1 += QEMU_TOS_FW_CONFIG_DTS=../build/qemu_v8/spmc_el1_manifest.dts
 TF_A_FLAGS_SPMC_AT_EL_1 += SPMC_OPTEE=1
+TF_A_FLAGS_SPMC_AT_EL_1 += QEMU_TOS_FW_CONFIG_DTS=../build/qemu_v8/spmc_el1_manifest.dts
+TF_A_FLAGS_SPMC_AT_EL_2  = SPD=spmd 
+TF_A_FLAGS_SPMC_AT_EL_2 += ENABLE_SPE_FOR_LOWER_ELS=0
+TF_A_FLAGS_SPMC_AT_EL_2 += ENABLE_SME_FOR_NS=0 ENABLE_SME_FOR_SWD=0
+TF_A_FLAGS_SPMC_AT_EL_2 += ENABLE_FEAT_SEL2=1
+TF_A_FLAGS_SPMC_AT_EL_2 += SP_LAYOUT_FILE=../build/qemu_v8/sp_layout.json
+TF_A_FLAGS_SPMC_AT_EL_2 += NEED_FDT=yes
+TF_A_FLAGS_SPMC_AT_EL_2 += BL32=$(HAFNIUM_BIN)
+TF_A_FLAGS_SPMC_AT_EL_2 += QEMU_TOS_FW_CONFIG_DTS=../build/qemu_v8/spmc_el2_manifest.dts
+TF_A_FLAGS_SPMC_AT_EL_2 += QEMU_TB_FW_CONFIG_DTS=../build/qemu_v8/tb_fw_config.dts
+ifneq ($(PAUTH),y)
+TF_A_FLAGS_SPMC_AT_EL_2 += CTX_INCLUDE_PAUTH_REGS=1
+endif
+ifneq ($(MEMTAG),y)
+TF_A_FLAGS_SPMC_AT_EL_2 += CTX_INCLUDE_MTE_REGS=1
+endif
 TF_A_FLAGS_SPMC_AT_EL_3  = SPD=spmd SPMC_AT_EL3=1
 TF_A_FLAGS_SPMC_AT_EL_3 += CTX_INCLUDE_EL2_REGS=0 SPMD_SPM_AT_SEL2=0
 TF_A_FLAGS_SPMC_AT_EL_3 += ENABLE_SME_FOR_NS=0 ENABLE_SME_FOR_SWD=0
@@ -198,7 +223,7 @@
 TF_A_FLAGS += CTX_INCLUDE_MTE_REGS=1
 endif
 
-arm-tf: optee-os $(BL33_DEPS)
+arm-tf: $(BL32_DEPS) $(BL33_DEPS)
 	$(TF_A_EXPORTS) $(MAKE) -C $(TF_A_PATH) $(TF_A_FLAGS) all fip
 	mkdir -p $(BINARIES_PATH)
 	ln -sf $(TF_A_OUT)/bl1.bin $(BINARIES_PATH)
@@ -218,12 +243,20 @@
 	rm -f $(BINARIES_PATH)/bl32_extra1.bin
 	rm -f $(BINARIES_PATH)/bl32_extra2.bin
 	rm -f $(BINARIES_PATH)/tos_fw_config.dtb
+	rm -f $(BINARIES_PATH)/op-tee.pkg
 ifeq ($(SPMC_AT_EL),1)
 	ln -sf $(TF_A_OUT)/fdts/spmc_el1_manifest.dtb \
 		$(BINARIES_PATH)/tos_fw_config.dtb
 	ln -sf $(OPTEE_OS_HEADER_V2_BIN) $(BINARIES_PATH)/bl32.bin
 	ln -sf $(OPTEE_OS_PAGER_V2_BIN) $(BINARIES_PATH)/bl32_extra1.bin
 	ln -sf $(OPTEE_OS_PAGEABLE_V2_BIN) $(BINARIES_PATH)/bl32_extra2.bin
+else ifeq ($(SPMC_AT_EL),2)
+	ln -sf $(TF_A_OUT)/fdts/spmc_el2_manifest.dtb \
+		$(BINARIES_PATH)/tos_fw_config.dtb
+	ln -sf $(TF_A_OUT)/fdts/tb_fw_config.dtb \
+		$(BINARIES_PATH)/tb_fw_config.dtb
+	ln -sf $(HAFNIUM_BIN) $(BINARIES_PATH)/bl32.bin
+	ln -sf $(TF_A_OUT)/op-tee.pkg $(BINARIES_PATH)/op-tee.pkg
 else ifeq ($(SPMC_AT_EL),3)
 	ln -sf $(TF_A_OUT)/fdts/spmc_el3_manifest.dtb \
 		$(BINARIES_PATH)/tos_fw_config.dtb
@@ -334,6 +367,13 @@
 ################################################################################
 OPTEE_OS_COMMON_FLAGS += DEBUG=$(DEBUG) CFG_ARM_GICV3=$(GICV3)
 OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_1 = CFG_CORE_SEL1_SPMC=y
+OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_2 = CFG_CORE_SEL2_SPMC=y
+OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_2 += CFG_ARM_GICV3=n CFG_CORE_HAFNIUM_INTC=y
+# [0e00.0000 0e2f.ffff] is reserved to early boot and SPMC
+# [0e30.0000 0e33.ffff] is reserved manifest etc (op-tee.pkg)
+OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_2 += CFG_TZDRAM_START=0x0e304000
+OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_2 += CFG_TZDRAM_SIZE=0x00cfc000
+OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_2 += CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME=n
 OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_3 = CFG_CORE_EL3_SPMC=y
 OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_3 += CFG_DT_ADDR=0x40000000
 OPTEE_OS_COMMON_FLAGS_SPMC_AT_EL_3 += CFG_CORE_RESERVED_SHM=n
@@ -357,6 +397,22 @@
 optee-os-clean: optee-os-clean-common
 
 ################################################################################
+# Hafnium
+################################################################################
+
+HAFNIUM_EXPORTS = PATH=$(HAFNIUM_PATH)/prebuilts/linux-x64/clang/bin:$(HAFNIUM_PATH)/prebuilts/linux-x64/dtc:$(PATH)
+
+.hafnium_checkout:
+	git -C $(HAFNIUM_PATH) submodule init --update
+	touch $@
+
+hafnium: $(HAFNIUM_BIN)
+
+$(HAFNIUM_BIN): .hafnium_checkout | $(OUT_PATH)
+	$(HAFNIUM_EXPORTS) $(MAKE) -C $(HAFNIUM_PATH) $(HAFNIUM_FLAGS) all
+
+
+################################################################################
 # mkimage - create images to be loaded by U-Boot
 ################################################################################
 # Without the objcopy, the uImage will be 10x bigger.
@@ -420,7 +476,11 @@
 QEMU_XEN	?= -drive if=none,file=$(XEN_EXT4),format=raw,id=hd1 \
 		   -device virtio-blk-device,drive=hd1
 else
+ifeq ($(SPMC_AT_EL),2)
+QEMU_VIRT	= true
+else
 QEMU_VIRT	= false
+endif
 ifeq ($(SPMC_AT_EL),n)
 QEMU_SME	= on
 else
@@ -433,6 +493,8 @@
 
 ifeq ($(MEMTAG),y)
 QEMU_MTE	= on
+else ifeq ($(SPMC_AT_EL),2)
+QEMU_MTE	= on
 else
 QEMU_MTE	= off
 endif