Browse Source

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.
pull/1937/head
Soby Mathew 5 years ago
committed by TrustedFirmware Code Review
parent
commit
8efec9e097
  1. 4
      docs/plat/qemu.rst
  2. 2
      include/lib/semihosting.h
  3. 34
      lib/semihosting/semihosting.c
  4. 21
      plat/qemu/common/qemu_bl2_setup.c
  5. 6
      plat/qemu/common/qemu_pm.c
  6. 10
      plat/qemu/qemu/platform.mk
  7. 10
      plat/qemu/qemu_sbsa/platform.mk

4
docs/plat/qemu.rst

@ -10,6 +10,10 @@ loop to be released by normal world via PSCI.
BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to 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. 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 An ARM64 defconfig v4.5 Linux kernel is known to boot, FDT doesn't need to be
provided as it's generated by QEMU. provided as it's generated by QEMU.

2
include/lib/semihosting.h

@ -23,6 +23,7 @@
#define SEMIHOSTING_SYS_REMOVE 0x0E #define SEMIHOSTING_SYS_REMOVE 0x0E
#define SEMIHOSTING_SYS_SYSTEM 0x12 #define SEMIHOSTING_SYS_SYSTEM 0x12
#define SEMIHOSTING_SYS_ERRNO 0x13 #define SEMIHOSTING_SYS_ERRNO 0x13
#define SEMIHOSTING_SYS_EXIT 0x18
#define FOPEN_MODE_R 0x0 #define FOPEN_MODE_R 0x0
#define FOPEN_MODE_RB 0x1 #define FOPEN_MODE_RB 0x1
@ -54,5 +55,6 @@ long semihosting_download_file(const char *file_name,
void semihosting_write_char(char character); void semihosting_write_char(char character);
void semihosting_write_string(char *string); void semihosting_write_string(char *string);
char semihosting_read_char(void); char semihosting_read_char(void);
void semihosting_exit(uint32_t reason, uint32_t subcode);
#endif /* SEMIHOSTING_H */ #endif /* SEMIHOSTING_H */

34
lib/semihosting/semihosting.c

@ -15,7 +15,7 @@
#endif #endif
long semihosting_call(unsigned long operation, long semihosting_call(unsigned long operation,
void *system_block_address); uintptr_t system_block_address);
typedef struct { typedef struct {
const char *file_name; const char *file_name;
@ -53,7 +53,7 @@ long semihosting_file_open(const char *file_name, size_t mode)
open_block.name_length = strlen(file_name); open_block.name_length = strlen(file_name);
return semihosting_call(SEMIHOSTING_SYS_OPEN, return semihosting_call(SEMIHOSTING_SYS_OPEN,
(void *) &open_block); (uintptr_t) &open_block);
} }
long semihosting_file_seek(long file_handle, ssize_t offset) long semihosting_file_seek(long file_handle, ssize_t offset)
@ -65,7 +65,7 @@ long semihosting_file_seek(long file_handle, ssize_t offset)
seek_block.location = offset; seek_block.location = offset;
result = semihosting_call(SEMIHOSTING_SYS_SEEK, result = semihosting_call(SEMIHOSTING_SYS_SEEK,
(void *) &seek_block); (uintptr_t) &seek_block);
if (result) if (result)
result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0); result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
@ -86,7 +86,7 @@ long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer)
read_block.length = *length; read_block.length = *length;
result = semihosting_call(SEMIHOSTING_SYS_READ, result = semihosting_call(SEMIHOSTING_SYS_READ,
(void *) &read_block); (uintptr_t) &read_block);
if (result == *length) { if (result == *length) {
return -EINVAL; return -EINVAL;
@ -112,7 +112,7 @@ long semihosting_file_write(long file_handle,
write_block.length = *length; write_block.length = *length;
result = semihosting_call(SEMIHOSTING_SYS_WRITE, result = semihosting_call(SEMIHOSTING_SYS_WRITE,
(void *) &write_block); (uintptr_t) &write_block);
*length = result; *length = result;
@ -122,28 +122,28 @@ long semihosting_file_write(long file_handle,
long semihosting_file_close(long file_handle) long semihosting_file_close(long file_handle)
{ {
return semihosting_call(SEMIHOSTING_SYS_CLOSE, return semihosting_call(SEMIHOSTING_SYS_CLOSE,
(void *) &file_handle); (uintptr_t) &file_handle);
} }
long semihosting_file_length(long file_handle) long semihosting_file_length(long file_handle)
{ {
return semihosting_call(SEMIHOSTING_SYS_FLEN, return semihosting_call(SEMIHOSTING_SYS_FLEN,
(void *) &file_handle); (uintptr_t) &file_handle);
} }
char semihosting_read_char(void) 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) 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) 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) long semihosting_system(char *command_line)
@ -154,7 +154,7 @@ long semihosting_system(char *command_line)
system_block.command_length = strlen(command_line); system_block.command_length = strlen(command_line);
return semihosting_call(SEMIHOSTING_SYS_SYSTEM, return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
(void *) &system_block); (uintptr_t) &system_block);
} }
long semihosting_get_flen(const char *file_name) long semihosting_get_flen(const char *file_name)
@ -216,3 +216,15 @@ semihosting_fail:
semihosting_file_close(file_handle); semihosting_file_close(file_handle);
return ret; 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
}

21
plat/qemu/common/qemu_bl2_setup.c

@ -51,7 +51,7 @@ static void security_setup(void)
static void update_dt(void) static void update_dt(void)
{ {
int ret; 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); ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
if (ret < 0) { if (ret < 0) {
@ -172,12 +172,12 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id)
* OP-TEE expect to receive DTB address in x2. * OP-TEE expect to receive DTB address in x2.
* This will be copied into x2 by dispatcher. * 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 */ #else /* case AARCH32_SP_OPTEE */
bl_mem_params->ep_info.args.arg0 = bl_mem_params->ep_info.args.arg0 =
bl_mem_params->ep_info.args.arg1; bl_mem_params->ep_info.args.arg1;
bl_mem_params->ep_info.args.arg1 = 0; 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; bl_mem_params->ep_info.args.arg3 = 0;
#endif #endif
#endif #endif
@ -192,8 +192,23 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id)
pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
#endif #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) */ /* BL33 expects to receive the primary CPU MPID (through r0) */
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
#endif
bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry(); bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
break; break;
default: default:

6
plat/qemu/common/qemu_pm.c

@ -10,10 +10,13 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/debug.h> #include <common/debug.h>
#include <lib/psci/psci.h> #include <lib/psci/psci.h>
#include <lib/semihosting.h>
#include <plat/common/platform.h> #include <plat/common/platform.h>
#include "qemu_private.h" #include "qemu_private.h"
#define ADP_STOPPED_APPLICATION_EXIT 0x20026
/* /*
* The secure entry point to be used on warm reset. * The secure entry point to be used on warm reset.
*/ */
@ -191,7 +194,8 @@ void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
******************************************************************************/ ******************************************************************************/
static void __dead2 qemu_system_off(void) 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(); panic();
} }

10
plat/qemu/qemu/platform.mk

@ -151,6 +151,8 @@ ifeq (${ARM_ARCH_MAJOR},8)
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \ BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a57.S \
lib/semihosting/semihosting.c \
lib/semihosting/${ARCH}/semihosting_call.S \
plat/common/plat_psci_common.c \ plat/common/plat_psci_common.c \
${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \
${PLAT_QEMU_COMMON_PATH}/topology.c \ ${PLAT_QEMU_COMMON_PATH}/topology.c \
@ -186,5 +188,13 @@ endif
# Process flags # Process flags
$(eval $(call add_define,BL32_RAM_LOCATION_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 # Do not enable SVE
ENABLE_SVE_FOR_NS := 0 ENABLE_SVE_FOR_NS := 0

10
plat/qemu/qemu_sbsa/platform.mk

@ -71,6 +71,8 @@ QEMU_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \
BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \ BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \ lib/cpus/aarch64/cortex_a57.S \
lib/semihosting/semihosting.c \
lib/semihosting/${ARCH}/semihosting_call.S \
plat/common/plat_psci_common.c \ plat/common/plat_psci_common.c \
${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \
${PLAT_QEMU_COMMON_PATH}/topology.c \ ${PLAT_QEMU_COMMON_PATH}/topology.c \
@ -97,5 +99,13 @@ PRELOADED_BL33_BASE ?= 0x10000000
BL32_RAM_LOCATION_ID = SEC_SRAM_ID BL32_RAM_LOCATION_ID = SEC_SRAM_ID
$(eval $(call add_define,BL32_RAM_LOCATION_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 # Do not enable SVE
ENABLE_SVE_FOR_NS := 0 ENABLE_SVE_FOR_NS := 0

Loading…
Cancel
Save