Merge changes I0fb7cf79,Ia8eb4710 into integration

* changes:
  qemu: Implement qemu_system_off via semihosting.
  qemu: Support ARM_LINUX_KERNEL_AS_BL33 to pass FDT address.
diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst
index 4ebe64b..a4c5bec 100644
--- a/docs/plat/qemu.rst
+++ b/docs/plat/qemu.rst
@@ -10,6 +10,10 @@
 BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to
 add a node describing PSCI and also enable methods for the CPUs.
 
+If ``ARM_LINUX_KERNEL_AS_BL33`` is set to 1 then this FDT will be passed to BL33
+via register x0, as expected by a Linux kernel. This allows a Linux kernel image
+to be booted directly as BL33 rather than using a bootloader.
+
 An ARM64 defconfig v4.5 Linux kernel is known to boot, FDT doesn't need to be
 provided as it's generated by QEMU.
 
diff --git a/include/lib/semihosting.h b/include/lib/semihosting.h
index 006c7b7..24b030c 100644
--- a/include/lib/semihosting.h
+++ b/include/lib/semihosting.h
@@ -23,6 +23,7 @@
 #define SEMIHOSTING_SYS_REMOVE          0x0E
 #define SEMIHOSTING_SYS_SYSTEM          0x12
 #define SEMIHOSTING_SYS_ERRNO           0x13
+#define SEMIHOSTING_SYS_EXIT            0x18
 
 #define FOPEN_MODE_R			0x0
 #define FOPEN_MODE_RB			0x1
@@ -54,5 +55,6 @@
 void semihosting_write_char(char character);
 void semihosting_write_string(char *string);
 char semihosting_read_char(void);
+void semihosting_exit(uint32_t reason, uint32_t subcode);
 
 #endif /* SEMIHOSTING_H */
diff --git a/lib/semihosting/semihosting.c b/lib/semihosting/semihosting.c
index 051dd00..60fc52a 100644
--- a/lib/semihosting/semihosting.c
+++ b/lib/semihosting/semihosting.c
@@ -15,7 +15,7 @@
 #endif
 
 long semihosting_call(unsigned long operation,
-			void *system_block_address);
+			uintptr_t system_block_address);
 
 typedef struct {
 	const char *file_name;
@@ -53,7 +53,7 @@
 	open_block.name_length = strlen(file_name);
 
 	return semihosting_call(SEMIHOSTING_SYS_OPEN,
-				(void *) &open_block);
+				(uintptr_t) &open_block);
 }
 
 long semihosting_file_seek(long file_handle, ssize_t offset)
@@ -65,7 +65,7 @@
 	seek_block.location = offset;
 
 	result = semihosting_call(SEMIHOSTING_SYS_SEEK,
-				  (void *) &seek_block);
+				  (uintptr_t) &seek_block);
 
 	if (result)
 		result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
@@ -86,7 +86,7 @@
 	read_block.length = *length;
 
 	result = semihosting_call(SEMIHOSTING_SYS_READ,
-				  (void *) &read_block);
+				  (uintptr_t) &read_block);
 
 	if (result == *length) {
 		return -EINVAL;
@@ -112,7 +112,7 @@
 	write_block.length = *length;
 
 	result = semihosting_call(SEMIHOSTING_SYS_WRITE,
-				   (void *) &write_block);
+				   (uintptr_t) &write_block);
 
 	*length = result;
 
@@ -122,28 +122,28 @@
 long semihosting_file_close(long file_handle)
 {
 	return semihosting_call(SEMIHOSTING_SYS_CLOSE,
-				(void *) &file_handle);
+				(uintptr_t) &file_handle);
 }
 
 long semihosting_file_length(long file_handle)
 {
 	return semihosting_call(SEMIHOSTING_SYS_FLEN,
-				(void *) &file_handle);
+				(uintptr_t) &file_handle);
 }
 
 char semihosting_read_char(void)
 {
-	return semihosting_call(SEMIHOSTING_SYS_READC, NULL);
+	return semihosting_call(SEMIHOSTING_SYS_READC, 0);
 }
 
 void semihosting_write_char(char character)
 {
-	semihosting_call(SEMIHOSTING_SYS_WRITEC, (void *) &character);
+	semihosting_call(SEMIHOSTING_SYS_WRITEC, (uintptr_t) &character);
 }
 
 void semihosting_write_string(char *string)
 {
-	semihosting_call(SEMIHOSTING_SYS_WRITE0, (void *) string);
+	semihosting_call(SEMIHOSTING_SYS_WRITE0, (uintptr_t) string);
 }
 
 long semihosting_system(char *command_line)
@@ -154,7 +154,7 @@
 	system_block.command_length = strlen(command_line);
 
 	return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
-				(void *) &system_block);
+				(uintptr_t) &system_block);
 }
 
 long semihosting_get_flen(const char *file_name)
@@ -216,3 +216,15 @@
 	semihosting_file_close(file_handle);
 	return ret;
 }
+
+void semihosting_exit(uint32_t reason, uint32_t subcode)
+{
+#ifdef __aarch64__
+	uint64_t parameters[] = {reason, subcode};
+
+	(void) semihosting_call(SEMIHOSTING_SYS_EXIT, (uintptr_t) &parameters);
+#else
+	/* The subcode is not supported on AArch32. */
+	(void) semihosting_call(SEMIHOSTING_SYS_EXIT, reason);
+#endif
+}
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index 166d245..3e289fc 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -51,7 +51,7 @@
 static void update_dt(void)
 {
 	int ret;
-	void *fdt = (void *)(uintptr_t)PLAT_QEMU_DT_BASE;
+	void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
 
 	ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
 	if (ret < 0) {
@@ -172,12 +172,12 @@
 		 * OP-TEE expect to receive DTB address in x2.
 		 * This will be copied into x2 by dispatcher.
 		 */
-		bl_mem_params->ep_info.args.arg3 = PLAT_QEMU_DT_BASE;
+		bl_mem_params->ep_info.args.arg3 = ARM_PRELOADED_DTB_BASE;
 #else /* case AARCH32_SP_OPTEE */
 		bl_mem_params->ep_info.args.arg0 =
 					bl_mem_params->ep_info.args.arg1;
 		bl_mem_params->ep_info.args.arg1 = 0;
-		bl_mem_params->ep_info.args.arg2 = PLAT_QEMU_DT_BASE;
+		bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
 		bl_mem_params->ep_info.args.arg3 = 0;
 #endif
 #endif
@@ -192,8 +192,23 @@
 		pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
 #endif
 
+#if ARM_LINUX_KERNEL_AS_BL33
+		/*
+		 * According to the file ``Documentation/arm64/booting.txt`` of
+		 * the Linux kernel tree, Linux expects the physical address of
+		 * the device tree blob (DTB) in x0, while x1-x3 are reserved
+		 * for future use and must be 0.
+		 */
+		bl_mem_params->ep_info.args.arg0 =
+			(u_register_t)ARM_PRELOADED_DTB_BASE;
+		bl_mem_params->ep_info.args.arg1 = 0U;
+		bl_mem_params->ep_info.args.arg2 = 0U;
+		bl_mem_params->ep_info.args.arg3 = 0U;
+#else
 		/* BL33 expects to receive the primary CPU MPID (through r0) */
 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+#endif
+
 		bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
 		break;
 	default:
diff --git a/plat/qemu/common/qemu_pm.c b/plat/qemu/common/qemu_pm.c
index a199688..116211c 100644
--- a/plat/qemu/common/qemu_pm.c
+++ b/plat/qemu/common/qemu_pm.c
@@ -10,10 +10,13 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <lib/psci/psci.h>
+#include <lib/semihosting.h>
 #include <plat/common/platform.h>
 
 #include "qemu_private.h"
 
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
 /*
  * The secure entry point to be used on warm reset.
  */
@@ -191,7 +194,8 @@
  ******************************************************************************/
 static void __dead2 qemu_system_off(void)
 {
-	ERROR("QEMU System Off: operation not handled.\n");
+	semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0);
+	ERROR("QEMU System Off: semihosting call unexpectedly returned.\n");
 	panic();
 }
 
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 5fda2cd..b95bf5a 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -151,6 +151,8 @@
 BL31_SOURCES		+=	lib/cpus/aarch64/aem_generic.S		\
 				lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a57.S		\
+				lib/semihosting/semihosting.c		\
+				lib/semihosting/${ARCH}/semihosting_call.S \
 				plat/common/plat_psci_common.c		\
 				${PLAT_QEMU_COMMON_PATH}/qemu_pm.c			\
 				${PLAT_QEMU_COMMON_PATH}/topology.c			\
@@ -186,5 +188,13 @@
 # Process flags
 $(eval $(call add_define,BL32_RAM_LOCATION_ID))
 
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33	:=	0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
 # Do not enable SVE
 ENABLE_SVE_FOR_NS	:=	0
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index 0d6047d..51832d0 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -71,6 +71,8 @@
 BL31_SOURCES		+=	lib/cpus/aarch64/aem_generic.S			\
 				lib/cpus/aarch64/cortex_a53.S			\
 				lib/cpus/aarch64/cortex_a57.S			\
+				lib/semihosting/semihosting.c			\
+				lib/semihosting/${ARCH}/semihosting_call.S	\
 				plat/common/plat_psci_common.c			\
 				${PLAT_QEMU_COMMON_PATH}/qemu_pm.c		\
 				${PLAT_QEMU_COMMON_PATH}/topology.c		\
@@ -97,5 +99,13 @@
 BL32_RAM_LOCATION_ID	= SEC_SRAM_ID
 $(eval $(call add_define,BL32_RAM_LOCATION_ID))
 
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33	:=	0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
 # Do not enable SVE
 ENABLE_SVE_FOR_NS	:= 0