qemu_v8.mk: Add option to add Xen in boot flow

Introduce option XEN_BOOT to add xen in the bootflow.

When built with XEN_BOOT=y, boot flow currently supported is :

BL1 -> BL2 -> BL31 -> OP-TEE -> uboot -> Xen -> Dom0

xtests can be run over Dom0

Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
Reviewed-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/common.mk b/common.mk
index 5ad5b41..ca4532b 100644
--- a/common.mk
+++ b/common.mk
@@ -284,7 +284,11 @@
 BR2_PACKAGE_OPTEE_TEST_EXT_WITH_TLS_TESTS := $(WITH_TLS_TESTS)
 BR2_PACKAGE_OPTEE_TEST_EXT_WITH_CXX_TESTS := $(WITH_CXX_TESTS)
 BR2_PACKAGE_STRACE ?= y
+ifeq ($(XEN_BOOT),y)
+BR2_TARGET_GENERIC_GETTY_PORT ?= "console"
+else
 BR2_TARGET_GENERIC_GETTY_PORT ?= $(if $(CFG_NW_CONSOLE_UART),ttyAMA$(CFG_NW_CONSOLE_UART),ttyAMA0)
+endif
 
 # Embed opensc for pkcs11-tool
 BR2_PACKAGE_OPENSC ?= y
diff --git a/kconfigs/u-boot_xen_qemu_v8.conf b/kconfigs/u-boot_xen_qemu_v8.conf
new file mode 100644
index 0000000..c7f81a4
--- /dev/null
+++ b/kconfigs/u-boot_xen_qemu_v8.conf
@@ -0,0 +1,3 @@
+CONFIG_SYS_TEXT_BASE=0x60000000
+CONFIG_BOOTCOMMAND="load virtio 0 $kernel_addr_r xen.efi && bootefi $kernel_addr_r"
+CONFIG_SEMIHOSTING=y
diff --git a/kconfigs/xen.conf b/kconfigs/xen.conf
new file mode 100644
index 0000000..7450658
--- /dev/null
+++ b/kconfigs/xen.conf
@@ -0,0 +1,30 @@
+CONFIG_EXPERT=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+
+# CONFIG_ACPI is not set
+# CONFIG_HAS_ITS is not set
+# CONFIG_EFI_SET_VIRTUAL_ADDRESS_MAP is not set
+# CONFIG_ARGO is not set
+
+# CONFIG_SCHED_ARINC653 is not set
+
+# CONFIG_SCHED_CREDIT_DEFAULT is not set
+CONFIG_SCHED_CREDIT2_DEFAULT=y
+# CONFIG_SCHED_RTDS_DEFAULT is not set
+# CONFIG_SCHED_NULL_DEFAULT is not set
+
+# CONFIG_IPMMU_VMSA is not set
+#
+# CONFIG_DEBUG is not set
+CONFIG_DEBUG_INFO=n
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_COVERAGE is not set
+# CONFIG_DEBUG_LOCK_PROFILE is not set
+# CONFIG_DEBUG_LOCKS is not set
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_VERBOSE_DEBUG is not set
+# CONFIG_DEVICE_TREE_DEBUG is not set
+# CONFIG_SCRUB_DEBUG is not set
+# CONFIG_DEBUG_TRACE is not set
+# CONFIG_XMEM_POOL_POISON is not set
diff --git a/qemu-check.exp b/qemu-check.exp
index 23f315d..03391f0 100644
--- a/qemu-check.exp
+++ b/qemu-check.exp
@@ -45,7 +45,11 @@
 spawn -open [open "|tail -f serial1.log"]
 set teecore $spawn_id
 if {[string first "aarch64" $::env(QEMU)] != -1} {
-	spawn $::env(QEMU) -nographic -serial mon:stdio -serial file:serial1.log -smp $::env(QEMU_SMP) -machine virt,secure=on,gic-version=$::env(QEMU_GIC) -cpu cortex-a57 -d unimp -semihosting-config enable=on,target=native -m 1057 -bios bl1.bin -initrd rootfs.cpio.gz -kernel Image -no-acpi -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2"
+	if {$::env(XEN_BOOT) == "y"} {
+		spawn $::env(QEMU) -nographic -serial mon:stdio -serial file:serial1.log -smp $::env(QEMU_SMP) -machine virt,secure=on,gic-version=$::env(QEMU_GIC),virtualization=true -cpu cortex-a57 -d unimp -semihosting-config enable=on,target=native -m $::env(QEMU_MEM) -bios bl1.bin -initrd rootfs.cpio.gz -kernel Image -no-acpi -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2" -drive if=none,file=xen.ext4,format=raw,id=hd1 -device virtio-blk-device,drive=hd1 -fsdev local,id=fsdev0,path=../..,security_model=none -device virtio-9p-device,fsdev=fsdev0,mount_tag=host
+	} else {
+		spawn $::env(QEMU) -nographic -serial mon:stdio -serial file:serial1.log -smp $::env(QEMU_SMP) -machine virt,secure=on,gic-version=$::env(QEMU_GIC) -cpu cortex-a57 -d unimp -semihosting-config enable=on,target=native -m $::env(QEMU_MEM) -bios bl1.bin -initrd rootfs.cpio.gz -kernel Image -no-acpi -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2"
+	}
 } else {
 	spawn $::env(QEMU) -nographic -monitor none -machine virt -machine secure=on -cpu cortex-a15 -smp $::env(QEMU_SMP) -d unimp -semihosting-config enable=on,target=native -m 1057 -serial stdio -serial file:serial1.log -bios $bios
 }
@@ -62,7 +66,11 @@
 }
 send -- "root\r\r"
 expect "# "
-info " done, guest is booted.\n"
+info " done, guest is booted"
+if {$::env(XEN_BOOT) == "y"} {
+        info " (Xen Dom0)"
+}
+info ".\n"
 # Toolchain libraries might be here or there
 send -- "export LD_LIBRARY_PATH=/lib:/lib/arm-linux-gnueabihf\r"
 expect "# "
diff --git a/qemu_v8.mk b/qemu_v8.mk
index 36519d6..9d6313f 100644
--- a/qemu_v8.mk
+++ b/qemu_v8.mk
@@ -19,6 +19,15 @@
 
 OPTEE_OS_PLATFORM = vexpress-qemu_armv8a
 
+########################################################################################
+# If you change this, you MUST run `make arm-tf-clean optee-os-clean` before rebuilding
+########################################################################################
+XEN_BOOT ?= n
+ifeq ($(XEN_BOOT),y)
+GICV3 = y
+UBOOT = y
+endif
+
 include common.mk
 
 DEBUG ?= 1
@@ -72,6 +81,12 @@
 BL33_DEPS		?= edk2
 endif
 
+XEN_PATH		?= $(ROOT)/xen
+XEN_IMAGE		?= $(XEN_PATH)/xen/xen.efi
+XEN_GZ			?= $(XEN_PATH)/xen/xen.gz
+XEN_EXT4		?= $(BINARIES_PATH)/xen.ext4
+XEN_CFG			?= $(ROOT)/build/qemu_v8/xen/xen.cfg
+
 ifeq ($(GICV3),y)
 	TFA_GIC_DRIVER	?= QEMU_GICV3
 	QEMU_GIC_VERSION = 3
@@ -96,6 +111,11 @@
 TARGET_CLEAN		+= edk2-clean
 endif
 
+ifeq ($(XEN_BOOT),y)
+TARGET_DEPS		+= xen xen-create-image
+TARGET_CLEAN		+= xen-clean
+endif
+
 all: $(TARGET_DEPS)
 
 clean: $(TARGET_CLEAN)
@@ -198,8 +218,13 @@
 ################################################################################
 # U-Boot
 ################################################################################
+ifeq ($(XEN_BOOT),y)
+UBOOT_DEFCONFIG_FILES := $(UBOOT_PATH)/configs/qemu_arm64_defconfig		\
+			 $(ROOT)/build/kconfigs/u-boot_xen_qemu_v8.conf
+else
 UBOOT_DEFCONFIG_FILES := $(UBOOT_PATH)/configs/qemu_arm64_defconfig		\
 			 $(ROOT)/build/kconfigs/u-boot_qemu_v8.conf
+endif
 
 UBOOT_COMMON_FLAGS ?= CROSS_COMPILE=$(CROSS_COMPILE_NS_KERNEL)
 
@@ -254,6 +279,9 @@
 # OP-TEE
 ################################################################################
 OPTEE_OS_COMMON_FLAGS += DEBUG=$(DEBUG) CFG_ARM_GICV3=$(GICV3)
+ifeq ($(XEN_BOOT),y)
+OPTEE_OS_COMMON_FLAGS += CFG_VIRTUALIZATION=y
+endif
 optee-os: optee-os-common
 
 optee-os-clean: optee-os-clean-common
@@ -297,6 +325,42 @@
 				-d $(ROOTFS_GZ) $(ROOTFS_UGZ)
 
 ################################################################################
+# XEN
+################################################################################
+.PHONY: xen
+$(XEN_PATH)/xen/.config:
+	$(MAKE) -C $(XEN_PATH)/xen XEN_TARGET_ARCH=arm64 defconfig
+	cd $(XEN_PATH)/xen && \
+	tools/kconfig/merge_config.sh -m .config $(ROOT)/build/kconfigs/xen.conf
+
+xen: $(XEN_PATH)/xen/.config
+	$(MAKE) -C $(XEN_PATH) dist-xen \
+	XEN_TARGET_ARCH=arm64 \
+	CONFIG_XEN_INSTALL_SUFFIX=.gz	\
+	CROSS_COMPILE="$(CCACHE)$(AARCH64_CROSS_COMPILE)"
+
+XEN_TMP ?= $(BINARIES_PATH)/xen_files
+
+$(XEN_TMP):
+	mkdir -p $@
+
+# virt-make-fs needs to be able to read the local kernel
+# See https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
+build-host-vmlinuz := $(shell echo /boot/vmlinuz-`uname -r`)
+$(if $(shell [ -r $(build-host-vmlinuz) ] || echo No), \
+  $(error $(build-host-vmlinuz) is unreadable. Please run: sudo chmod a+r $(build-host-vmlinuz) and try again))
+
+xen-create-image: xen linux buildroot | $(XEN_TMP)
+	cp $(KERNEL_IMAGE) $(XEN_TMP)
+	cp $(XEN_IMAGE) $(XEN_TMP)
+	cp $(XEN_CFG) $(XEN_TMP)
+	cp $(ROOT)/out-br/images/rootfs.cpio.gz $(XEN_TMP)
+	virt-make-fs -t vfat $(XEN_TMP) $(XEN_EXT4)
+
+xen-clean:
+	$(MAKE) -C $(XEN_PATH) clean
+
+################################################################################
 # Run targets
 ################################################################################
 .PHONY: run
@@ -304,7 +368,18 @@
 run: all
 	$(MAKE) run-only
 
-QEMU_SMP ?= 2
+
+ifeq ($(XEN_BOOT),y)
+QEMU_MEM 	?= 2048
+QEMU_SMP	?= 4
+QEMU_VIRT	= true
+QEMU_XEN	?= -drive if=none,file=$(XEN_EXT4),format=raw,id=hd1 \
+		   -device virtio-blk-device,drive=hd1
+else
+QEMU_SMP 	?= 2
+QEMU_MEM 	?= 1057
+QEMU_VIRT	= false
+endif
 
 .PHONY: run-only
 run-only:
@@ -318,14 +393,15 @@
 		-nographic \
 		-serial tcp:localhost:54320 -serial tcp:localhost:54321 \
 		-smp $(QEMU_SMP) \
-		-s -S -machine virt,secure=on,gic-version=$(QEMU_GIC_VERSION) \
+		-s -S -machine virt,secure=on,gic-version=$(QEMU_GIC_VERSION),virtualization=$(QEMU_VIRT) \
 		-cpu cortex-a57 \
 		-d unimp -semihosting-config enable=on,target=native \
-		-m 1057 \
-		-bios bl1.bin \
+		-m $(QEMU_MEM) \
+		-bios bl1.bin		\
 		-initrd rootfs.cpio.gz \
 		-kernel Image -no-acpi \
 		-append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2 $(QEMU_KERNEL_BOOTARGS)' \
+		$(QEMU_XEN) \
 		$(QEMU_EXTRA_ARGS)
 
 ifneq ($(filter check,$(MAKECMDGOALS)),)
@@ -342,6 +418,8 @@
 		export QEMU=$(QEMU_BUILD)/aarch64-softmmu/qemu-system-aarch64 && \
 		export QEMU_SMP=$(QEMU_SMP) && \
 		export QEMU_GIC=$(QEMU_GIC_VERSION) && \
+		export QEMU_MEM=$(QEMU_MEM) && \
+		export XEN_BOOT=$(XEN_BOOT) && \
 		expect $(ROOT)/build/qemu-check.exp -- $(check-args) || \
 		(if [ "$(DUMP_LOGS_ON_ERROR)" ]; then \
 			echo "== $$PWD/serial0.log:"; \
diff --git a/qemu_v8/xen/xen.cfg b/qemu_v8/xen/xen.cfg
new file mode 100644
index 0000000..4ce3d77
--- /dev/null
+++ b/qemu_v8/xen/xen.cfg
@@ -0,0 +1,7 @@
+[global]
+default=buildroot
+
+[buildroot]
+options=console=dtuart noreboot dom0_mem=1G
+kernel=Image rw root=/dev/ram console=hvc0 earlycon=xenboot
+ramdisk=rootfs.cpio.gz