diff options
Diffstat (limited to 'plat/qemu')
-rw-r--r-- | plat/qemu/common/aarch32/plat_helpers.S | 6 | ||||
-rw-r--r-- | plat/qemu/common/aarch64/plat_helpers.S | 9 | ||||
-rw-r--r-- | plat/qemu/common/qemu_common.c | 20 | ||||
-rw-r--r-- | plat/qemu/common/qemu_console.c | 4 | ||||
-rw-r--r-- | plat/qemu/common/qemu_io_storage.c | 71 | ||||
-rw-r--r-- | plat/qemu/common/qemu_spm.c | 138 | ||||
-rw-r--r-- | plat/qemu/common/qemu_stack_protector.c | 16 | ||||
-rw-r--r-- | plat/qemu/qemu/include/platform_def.h | 14 | ||||
-rw-r--r-- | plat/qemu/qemu/platform.mk | 33 | ||||
-rw-r--r-- | plat/qemu/qemu_sbsa/include/platform_def.h | 183 | ||||
-rw-r--r-- | plat/qemu/qemu_sbsa/platform.mk | 34 | ||||
-rw-r--r-- | plat/qemu/qemu_sbsa/sbsa_pm.c | 237 | ||||
-rw-r--r-- | plat/qemu/qemu_sbsa/sbsa_private.h | 17 | ||||
-rw-r--r-- | plat/qemu/qemu_sbsa/sbsa_topology.c | 63 |
14 files changed, 780 insertions, 65 deletions
diff --git a/plat/qemu/common/aarch32/plat_helpers.S b/plat/qemu/common/aarch32/plat_helpers.S index 15e860b42..5e346d585 100644 --- a/plat/qemu/common/aarch32/plat_helpers.S +++ b/plat/qemu/common/aarch32/plat_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -125,10 +125,10 @@ func plat_crash_console_putc endfunc plat_crash_console_putc /* --------------------------------------------- - * int plat_crash_console_flush(int c) + * void plat_crash_console_flush(int c) * Function to force a write of all buffered * data that hasn't been output. - * Out : return -1 on error else return 0. + * Out : void. * Clobber list : x0, x1 * --------------------------------------------- */ diff --git a/plat/qemu/common/aarch64/plat_helpers.S b/plat/qemu/common/aarch64/plat_helpers.S index dbcdc2d39..08b281735 100644 --- a/plat/qemu/common/aarch64/plat_helpers.S +++ b/plat/qemu/common/aarch64/plat_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -32,7 +32,8 @@ endfunc plat_my_core_pos func plat_qemu_calc_core_pos and x1, x0, #MPIDR_CPU_MASK and x0, x0, #MPIDR_CLUSTER_MASK - add x0, x1, x0, LSR #6 + add x0, x1, x0, LSR #(MPIDR_AFFINITY_BITS -\ + PLATFORM_CPU_PER_CLUSTER_SHIFT) ret endfunc plat_qemu_calc_core_pos @@ -121,10 +122,10 @@ func plat_crash_console_putc endfunc plat_crash_console_putc /* --------------------------------------------- - * int plat_crash_console_flush(int c) + * void plat_crash_console_flush(int c) * Function to force a write of all buffered * data that hasn't been output. - * Out : return -1 on error else return 0. + * Out : void. * Clobber list : x0, x1 * --------------------------------------------- */ diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c index 365cfb7f0..47ec79114 100644 --- a/plat/qemu/common/qemu_common.c +++ b/plat/qemu/common/qemu_common.c @@ -1,5 +1,6 @@ + /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,7 +26,7 @@ #ifdef DEVICE2_BASE #define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \ DEVICE2_SIZE, \ - MT_DEVICE | MT_RO | MT_SECURE) + MT_DEVICE | MT_RW | MT_SECURE) #endif #define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ @@ -77,7 +78,11 @@ static const mmap_region_t plat_qemu_mmap[] = { MAP_DEVICE2, #endif MAP_NS_DRAM0, +#if SPM_MM + QEMU_SP_IMAGE_MMAP, +#else MAP_BL32_MEM, +#endif {0} }; #endif @@ -88,7 +93,15 @@ static const mmap_region_t plat_qemu_mmap[] = { #ifdef MAP_DEVICE1 MAP_DEVICE1, #endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif +#if SPM_MM + MAP_NS_DRAM0, + QEMU_SPM_BUF_EL3_MMAP, +#else MAP_BL32_MEM, +#endif {0} }; #endif @@ -99,6 +112,9 @@ static const mmap_region_t plat_qemu_mmap[] = { #ifdef MAP_DEVICE1 MAP_DEVICE1, #endif +#ifdef MAP_DEVICE2 + MAP_DEVICE2, +#endif {0} }; #endif diff --git a/plat/qemu/common/qemu_console.c b/plat/qemu/common/qemu_console.c index fec182892..1f00f8a72 100644 --- a/plat/qemu/common/qemu_console.c +++ b/plat/qemu/common/qemu_console.c @@ -9,7 +9,7 @@ #include <drivers/console.h> #include <drivers/arm/pl011.h> -static console_pl011_t console; +static console_t console; void qemu_console_init(void) { @@ -17,7 +17,7 @@ void qemu_console_init(void) PLAT_QEMU_BOOT_UART_CLK_IN_HZ, PLAT_QEMU_CONSOLE_BAUDRATE, &console); - console_set_scope(&console.console, CONSOLE_FLAG_BOOT | + console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); } diff --git a/plat/qemu/common/qemu_io_storage.c b/plat/qemu/common/qemu_io_storage.c index 0e81cd199..1107e443f 100644 --- a/plat/qemu/common/qemu_io_storage.c +++ b/plat/qemu/common/qemu_io_storage.c @@ -12,6 +12,7 @@ #include <common/bl_common.h> #include <common/debug.h> #include <drivers/io/io_driver.h> +#include <drivers/io/io_encrypted.h> #include <drivers/io/io_fip.h> #include <drivers/io/io_memmap.h> #include <drivers/io/io_semihosting.h> @@ -47,6 +48,10 @@ static const io_dev_connector_t *memmap_dev_con; static uintptr_t memmap_dev_handle; static const io_dev_connector_t *sh_dev_con; static uintptr_t sh_dev_handle; +#ifndef DECRYPTION_SUPPORT_none +static const io_dev_connector_t *enc_dev_con; +static uintptr_t enc_dev_handle; +#endif static const io_block_spec_t fip_block_spec = { .offset = PLAT_QEMU_FIP_BASE, @@ -172,10 +177,11 @@ static const io_file_spec_t sh_file_spec[] = { #endif /* TRUSTED_BOARD_BOOT */ }; - - static int open_fip(const uintptr_t spec); static int open_memmap(const uintptr_t spec); +#ifndef DECRYPTION_SUPPORT_none +static int open_enc_fip(const uintptr_t spec); +#endif struct plat_io_policy { uintptr_t *dev_handle; @@ -190,16 +196,46 @@ static const struct plat_io_policy policies[] = { (uintptr_t)&fip_block_spec, open_memmap }, + [ENC_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)NULL, + open_fip + }, [BL2_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl2_uuid_spec, open_fip }, +#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none) + [BL31_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_enc_fip + }, +#else [BL31_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl31_uuid_spec, open_fip }, +#endif +#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none) + [BL32_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_enc_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_enc_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &enc_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_enc_fip + }, +#else [BL32_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl32_uuid_spec, @@ -215,6 +251,7 @@ static const struct plat_io_policy policies[] = { (uintptr_t)&bl32_extra2_uuid_spec, open_fip }, +#endif [BL33_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl33_uuid_spec, @@ -271,7 +308,7 @@ static int open_fip(const uintptr_t spec) /* See if a Firmware Image Package is available */ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); - if (result == 0) { + if (result == 0 && spec != (uintptr_t)NULL) { result = io_open(fip_dev_handle, spec, &local_image_handle); if (result == 0) { VERBOSE("Using FIP\n"); @@ -281,6 +318,25 @@ static int open_fip(const uintptr_t spec) return result; } +#ifndef DECRYPTION_SUPPORT_none +static int open_enc_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if an encrypted FIP is available */ + result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID); + if (result == 0) { + result = io_open(enc_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using encrypted FIP\n"); + io_close(local_image_handle); + } + } + return result; +} +#endif + static int open_memmap(const uintptr_t spec) { int result; @@ -333,6 +389,15 @@ void plat_qemu_io_setup(void) &memmap_dev_handle); assert(io_result == 0); +#ifndef DECRYPTION_SUPPORT_none + io_result = register_io_dev_enc(&enc_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL, + &enc_dev_handle); + assert(io_result == 0); +#endif + /* Register the additional IO devices on this platform */ io_result = register_io_dev_sh(&sh_dev_con); assert(io_result == 0); diff --git a/plat/qemu/common/qemu_spm.c b/plat/qemu/common/qemu_spm.c new file mode 100644 index 000000000..93dd2b37d --- /dev/null +++ b/plat/qemu/common/qemu_spm.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved. + */ + +#include <libfdt.h> + +#include <bl31/ehf.h> +#include <common/debug.h> +#include <common/fdt_fixup.h> +#include <common/fdt_wrappers.h> +#include <lib/xlat_tables/xlat_tables_compat.h> +#include <services/spm_mm_partition.h> + +#include <platform_def.h> + +/* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */ +#define MAP_DEVICE1_EL0 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) + +mmap_region_t plat_qemu_secure_partition_mmap[] = { + QEMU_SP_IMAGE_NS_BUF_MMAP, /* must be placed at first entry */ + MAP_DEVICE1_EL0, /* for the UART */ + QEMU_SP_IMAGE_MMAP, + QEMU_SPM_BUF_EL0_MMAP, + QEMU_SP_IMAGE_RW_MMAP, + MAP_SECURE_VARSTORE, + {0} +}; + +/* + * Boot information passed to a secure partition during initialisation. + * Linear indices in MP information will be filled at runtime. + */ +static spm_mm_mp_info_t sp_mp_info[] = { + [0] = {0x80000000, 0}, + [1] = {0x80000001, 0}, + [2] = {0x80000002, 0}, + [3] = {0x80000003, 0}, + [4] = {0x80000004, 0}, + [5] = {0x80000005, 0}, + [6] = {0x80000006, 0}, + [7] = {0x80000007, 0} +}; + +spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(spm_mm_boot_info_t), + .h.attr = 0, + .sp_mem_base = PLAT_QEMU_SP_IMAGE_BASE, + .sp_mem_limit = BL32_LIMIT, + .sp_image_base = PLAT_QEMU_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = PLAT_QEMU_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = PLAT_QEMU_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = PLAT_QEMU_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = sp_mp_info +}; + +/* Enumeration of priority levels on QEMU platforms. */ +ehf_pri_desc_t qemu_exceptions[] = { + EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI) +}; + +int dt_add_ns_buf_node(uintptr_t *base) +{ + uintptr_t addr; + size_t size; + uintptr_t ns_buf_addr; + int node; + int err; + void *fdt = (void *)ARM_PRELOADED_DTB_BASE; + + err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE); + if (err < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", fdt, err); + return err; + } + + /* + * reserved-memory for standaloneMM non-secure buffer + * is allocated at the top of the first system memory region. + */ + node = fdt_path_offset(fdt, "/memory"); + + err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size); + if (err < 0) { + ERROR("Failed to get the memory node information\n"); + return err; + } + INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1); + + ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr, + ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1); + + err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr, + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE); + if (err < 0) { + ERROR("Failed to add the reserved-memory node\n"); + return err; + } + + *base = ns_buf_addr; + return 0; +} + +/* Plug in QEMU exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions), + QEMU_PRI_BITS); + +const mmap_region_t *plat_get_secure_partition_mmap(void *cookie) +{ + uintptr_t ns_buf_base; + + dt_add_ns_buf_node(&ns_buf_base); + + plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base; + plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base; + plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base; + + return plat_qemu_secure_partition_mmap; +} + +const spm_mm_boot_info_t * +plat_get_secure_partition_boot_info(void *cookie) +{ + return &plat_qemu_secure_partition_boot_info; +} diff --git a/plat/qemu/common/qemu_stack_protector.c b/plat/qemu/common/qemu_stack_protector.c index c226158ad..15ce3d6d2 100644 --- a/plat/qemu/common/qemu_stack_protector.c +++ b/plat/qemu/common/qemu_stack_protector.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,17 +7,25 @@ #include <stdint.h> #include <arch_helpers.h> +#include <arch_features.h> #include <plat/common/platform.h> #define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL) u_register_t plat_get_stack_protector_canary(void) { +#if ENABLE_FEAT_RNG + /* Use the RNDR instruction if the CPU supports it */ + if (is_armv8_5_rng_present()) { + return read_rndr(); + } +#endif + /* - * Ideally, a random number should be returned instead of the + * Ideally, a random number should be returned above. If a random + * number generator is not supported, return instead a * combination of a timer's value and a compile-time constant. - * As the virt platform does not have any random number generator, - * this is better than nothing but not necessarily really secure. + * This is better than nothing but not necessarily really secure. */ return RANDOM_CANARY_VALUE ^ read_cntpct_el0(); } diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h index cce992ff9..e6bb1e6a9 100644 --- a/plat/qemu/qemu/include/platform_def.h +++ b/plat/qemu/qemu/include/platform_def.h @@ -24,6 +24,14 @@ #define PLATFORM_CLUSTER1_CORE_COUNT U(0) #else #define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(2) = 4 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2) + #define PLATFORM_CLUSTER_COUNT U(2) #define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER #define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER @@ -172,7 +180,7 @@ #define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) #define MAX_MMAP_REGIONS 11 #define MAX_XLAT_TABLES 6 -#define MAX_IO_DEVICES 3 +#define MAX_IO_DEVICES 4 #define MAX_IO_HANDLES 4 /* @@ -196,8 +204,8 @@ #define QEMU_FLASH1_BASE 0x04000000 #define QEMU_FLASH1_SIZE 0x04000000 -#define PLAT_QEMU_FIP_BASE QEMU_FLASH1_BASE -#define PLAT_QEMU_FIP_MAX_SIZE QEMU_FLASH1_SIZE +#define PLAT_QEMU_FIP_BASE 0x00040000 +#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000 #define DEVICE0_BASE 0x08000000 #define DEVICE0_SIZE 0x01000000 diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk index b95bf5a51..14bf049be 100644 --- a/plat/qemu/qemu/platform.mk +++ b/plat/qemu/qemu/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -15,6 +15,7 @@ ifeq (${ARM_ARCH_MAJOR},7) MARCH32_DIRECTIVE := -mcpu=cortex-a15 $(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) $(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER)) +$(eval $(call add_define,ARMV7_SUPPORTS_VFP)) # Qemu expects a BL32 boot stage. NEED_BL32 := yes endif # ARMv7 @@ -58,18 +59,20 @@ ifneq (${TRUSTED_BOARD_BOOT},0) AUTH_SOURCES := drivers/auth/auth_mod.c \ drivers/auth/crypto_mod.c \ drivers/auth/img_parser_mod.c \ - drivers/auth/tbbr/tbbr_cot.c + drivers/auth/tbbr/tbbr_cot_common.c BL1_SOURCES += ${AUTH_SOURCES} \ bl1/tbbr/tbbr_img_desc.c \ plat/common/tbbr/plat_tbbr.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \ - $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S + $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl1.c BL2_SOURCES += ${AUTH_SOURCES} \ plat/common/tbbr/plat_tbbr.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \ - $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S + $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \ + drivers/auth/tbbr/tbbr_cot_bl2.c ROT_KEY = $(BUILD_PLAT)/rot_key.pem ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin @@ -81,7 +84,7 @@ ifneq (${TRUSTED_BOARD_BOOT},0) certificates: $(ROT_KEY) - $(ROT_KEY): + $(ROT_KEY): | $(BUILD_PLAT) @echo " OPENSSL $@" $(Q)openssl genrsa 2048 > $@ 2>/dev/null @@ -127,15 +130,21 @@ ifeq ($(add-lib-optee),yes) BL2_SOURCES += lib/optee/optee_utils.c endif +ifneq (${DECRYPTION_SUPPORT},none) +BL1_SOURCES += drivers/io/io_encrypted.c +BL2_SOURCES += drivers/io/io_encrypted.c +endif + QEMU_GICV2_SOURCES := drivers/arm/gic/v2/gicv2_helpers.c \ drivers/arm/gic/v2/gicv2_main.c \ drivers/arm/gic/common/gic_common.c \ plat/common/plat_gicv2.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv2.c -QEMU_GICV3_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ - drivers/arm/gic/v3/gicv3_main.c \ - drivers/arm/gic/common/gic_common.c \ +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +QEMU_GICV3_SOURCES := ${GICV3_SOURCES} \ plat/common/plat_gicv3.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c @@ -164,11 +173,19 @@ endif # Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images # in the FIP if the platform requires. ifneq ($(BL32_EXTRA1),) +ifneq (${DECRYPTION_SUPPORT},none) +$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32))) +else $(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1)) endif +endif ifneq ($(BL32_EXTRA2),) +ifneq (${DECRYPTION_SUPPORT},none) +$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32))) +else $(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2)) endif +endif SEPARATE_CODE_AND_RODATA := 1 ENABLE_STACK_PROTECTOR := 0 diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h index f44b9f6e0..b69c2ebef 100644 --- a/plat/qemu/qemu_sbsa/include/platform_def.h +++ b/plat/qemu/qemu_sbsa/include/platform_def.h @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited and Contributors. + * All rights reserved. */ -#ifndef __PLATFORM_DEF_H__ -#define __PLATFORM_DEF_H__ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H #include <arch.h> #include <plat/common/common_def.h> @@ -15,13 +16,17 @@ #define PLATFORM_STACK_SIZE 0x1000 -#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) -#define PLATFORM_CLUSTER_COUNT U(2) -#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER -#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER -#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ - PLATFORM_CLUSTER1_CORE_COUNT) - +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) +/* + * Define the number of cores per cluster used in calculating core position. + * The cluster number is shifted by this value and added to the core ID, + * so its value represents log2(cores/cluster). + * Default is 2**(3) = 8 cores per cluster. + */ +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(3) +#define PLATFORM_CLUSTER_COUNT U(64) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) #define QEMU_PRIMARY_CPU U(0) #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ @@ -84,7 +89,7 @@ */ #define SHARED_RAM_BASE SEC_SRAM_BASE -#define SHARED_RAM_SIZE 0x00001000 +#define SHARED_RAM_SIZE 0x00002000 #define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE #define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE) @@ -107,9 +112,10 @@ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using * the current BL1 RW debug size plus a little space for growth. */ +#define BL1_SIZE 0x12000 #define BL1_RO_BASE SEC_ROM_BASE #define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) -#define BL1_RW_BASE (BL1_RW_LIMIT - 0x12000) +#define BL1_RW_BASE (BL1_RW_LIMIT - BL1_SIZE) #define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) /* @@ -118,7 +124,8 @@ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug * size plus a little space for growth. */ -#define BL2_BASE (BL31_BASE - 0x1D000) +#define BL2_SIZE 0x1D000 +#define BL2_BASE (BL31_BASE - BL2_SIZE) #define BL2_LIMIT BL31_BASE /* @@ -127,8 +134,9 @@ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the * current BL3-1 debug size plus a little space for growth. */ -#define BL31_BASE (BL31_LIMIT - 0x20000) -#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_SIZE 0x300000 +#define BL31_BASE (BL31_LIMIT - BL31_SIZE) +#define BL31_LIMIT (BL1_RW_BASE) #define BL31_PROGBITS_LIMIT BL1_RW_BASE @@ -138,12 +146,11 @@ * BL3-2 can execute from Secure SRAM, or Secure DRAM. */ #define BL32_SRAM_BASE BL_RAM_BASE -#define BL32_SRAM_LIMIT BL31_BASE -#define BL32_DRAM_BASE SEC_DRAM_BASE -#define BL32_DRAM_LIMIT (SEC_DRAM_BASE + SEC_DRAM_SIZE) +#define BL32_SRAM_LIMIT BL2_BASE #define BL32_MEM_BASE BL_RAM_BASE -#define BL32_MEM_SIZE BL_RAM_SIZE +#define BL32_MEM_SIZE (BL_RAM_SIZE - BL1_SIZE - \ + BL2_SIZE - BL31_SIZE) #define BL32_BASE BL32_SRAM_BASE #define BL32_LIMIT BL32_SRAM_LIMIT @@ -152,11 +159,21 @@ #define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 42) #define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42) +#if SPM_MM +#define MAX_MMAP_REGIONS 12 +#define MAX_XLAT_TABLES 12 +#else #define MAX_MMAP_REGIONS 11 -#define MAX_XLAT_TABLES 10 +#define MAX_XLAT_TABLES 11 +#endif #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4 +#if SPM_MM && defined(IMAGE_BL31) +# define PLAT_SP_IMAGE_MMAP_REGIONS 30 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 20 +#endif + /* * PL011 related constants */ @@ -165,6 +182,10 @@ #define UART0_CLK_IN_HZ 1 #define UART1_CLK_IN_HZ 1 +/* Secure UART */ +#define UART2_BASE 0x60040000 +#define UART2_CLK_IN_HZ 1 + #define PLAT_QEMU_BOOT_UART_BASE UART0_BASE #define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ @@ -179,14 +200,17 @@ #define QEMU_FLASH1_SIZE 0x10000000 #define PLAT_QEMU_FIP_BASE 0x00008000 -#define PLAT_QEMU_FIP_MAX_SIZE 0x00020000 +#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000 /* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */ #define DEVICE0_BASE 0x40000000 #define DEVICE0_SIZE 0x04080000 /* This is map from NORMAL_UART up to SECURE_UART_MM */ #define DEVICE1_BASE 0x60000000 -#define DEVICE1_SIZE 0x00041000 +#define DEVICE1_SIZE 0x10041000 +/* This is a map for SECURE_EC */ +#define DEVICE2_BASE 0x50000000 +#define DEVICE2_SIZE 0x00001000 /* * GIC related constants @@ -233,11 +257,122 @@ * DT related constants */ #define PLAT_QEMU_DT_BASE NS_DRAM0_BASE -#define PLAT_QEMU_DT_MAX_SIZE 0x10000 +#define PLAT_QEMU_DT_MAX_SIZE 0x100000 /* * System counter */ #define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16) -#endif /* __PLATFORM_DEF_H__ */ +#if SPM_MM +#define PLAT_QEMU_SP_IMAGE_BASE BL_RAM_BASE +#define PLAT_QEMU_SP_IMAGE_SIZE ULL(0x300000) + +#ifdef IMAGE_BL2 +/* In BL2 all memory allocated to the SPM Payload image is marked as RW. */ +# define QEMU_SP_IMAGE_MMAP MAP_REGION_FLAT( \ + PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_SIZE, \ + MT_MEMORY | MT_RW | \ + MT_SECURE) +#elif IMAGE_BL31 +/* All SPM Payload memory is marked as code in S-EL0 */ +# define QEMU_SP_IMAGE_MMAP MAP_REGION2(PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_BASE, \ + PLAT_QEMU_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | \ + MT_USER, \ + PAGE_SIZE) +#endif + +/* + * EL3 -> S-EL0 secure shared memory + */ +#define PLAT_SPM_BUF_PCPU_SIZE ULL(0x10000) +#define PLAT_SPM_BUF_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SPM_BUF_PCPU_SIZE) +#define PLAT_SPM_BUF_BASE (BL32_LIMIT - PLAT_SPM_BUF_SIZE) + +#define QEMU_SPM_BUF_EL3_MMAP MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RW_DATA | MT_SECURE) + +#define QEMU_SPM_BUF_EL0_MMAP MAP_REGION2(PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RO_DATA | MT_SECURE | \ + MT_USER, \ + PAGE_SIZE) + +/* + * Shared memory between Normal world and S-EL0 for + * passing data during service requests. It will be marked as RW and NS. + * This buffer is allocated at the top of NS_DRAM, the base address is + * overridden in SPM initialization. + */ +#define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE (PLAT_QEMU_DT_BASE + \ + PLAT_QEMU_DT_MAX_SIZE) +#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x200000) + +#define QEMU_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \ + PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ + PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \ + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, \ + MT_RW_DATA | MT_NS | \ + MT_USER, \ + PAGE_SIZE) + +#define PLAT_SP_IMAGE_NS_BUF_BASE PLAT_QEMU_SP_IMAGE_NS_BUF_BASE +#define PLAT_SP_IMAGE_NS_BUF_SIZE PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE + +#define PLAT_QEMU_SP_IMAGE_HEAP_BASE (PLAT_QEMU_SP_IMAGE_BASE + \ + PLAT_QEMU_SP_IMAGE_SIZE) +#define PLAT_QEMU_SP_IMAGE_HEAP_SIZE ULL(0x800000) + +#define PLAT_SP_IMAGE_STACK_BASE (PLAT_QEMU_SP_IMAGE_HEAP_BASE + \ + PLAT_QEMU_SP_IMAGE_HEAP_SIZE) +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000) +#define QEMU_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SP_IMAGE_STACK_PCPU_SIZE) + +#define QEMU_SP_IMAGE_RW_MMAP MAP_REGION2( \ + PLAT_QEMU_SP_IMAGE_HEAP_BASE, \ + PLAT_QEMU_SP_IMAGE_HEAP_BASE, \ + (QEMU_SP_IMAGE_STACK_TOTAL_SIZE + \ + PLAT_QEMU_SP_IMAGE_HEAP_SIZE), \ + MT_RW_DATA | MT_SECURE | \ + MT_USER, \ + PAGE_SIZE) + +/* + * Secure variable storage is located at Secure Flash. + */ +#if SPM_MM +#define QEMU_SECURE_VARSTORE_BASE 0x01000000 +#define QEMU_SECURE_VARSTORE_SIZE 0x00100000 +#define MAP_SECURE_VARSTORE MAP_REGION_FLAT( \ + QEMU_SECURE_VARSTORE_BASE, \ + QEMU_SECURE_VARSTORE_SIZE, \ + MT_MEMORY | MT_RW | \ + MT_SECURE | MT_USER) +#endif + +/* Total number of memory regions with distinct properties */ +#define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS 6 + +/* + * Name of the section to put the translation tables used by the S-EL1/S-EL0 + * context of a Secure Partition. + */ +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "qemu_sp_xlat_table" +#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "qemu_sp_xlat_table" + +/* Cookies passed to the Secure Partition at boot. Not used by QEMU platforms.*/ +#define PLAT_SPM_COOKIE_0 ULL(0) +#define PLAT_SPM_COOKIE_1 ULL(0) +#endif + +#define QEMU_PRI_BITS 2 +#define PLAT_SP_PRI 0x20 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk index 51832d0ff..d45f3f156 100644 --- a/plat/qemu/qemu_sbsa/platform.mk +++ b/plat/qemu/qemu_sbsa/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved. +# Copyright (c) 2019-2020, Linaro Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -8,6 +8,12 @@ CRASH_REPORTING := 1 include lib/libfdt/libfdt.mk +ifeq (${SPM_MM},1) +NEED_BL32 := yes +EL3_EXCEPTION_HANDLING := 1 +GICV2_G0_FOR_EL3 := 1 +endif + # Enable new version of image loading on QEMU platforms LOAD_IMAGE_V2 := 1 @@ -41,9 +47,8 @@ BL1_SOURCES += drivers/io/io_semihosting.c \ ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \ ${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c -BL1_SOURCES += lib/cpus/aarch64/aem_generic.S \ - lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S +BL1_SOURCES += lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S BL2_SOURCES += drivers/io/io_semihosting.c \ drivers/io/io_storage.c \ @@ -62,23 +67,28 @@ BL2_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \ common/desc_image_load.c endif -QEMU_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ - drivers/arm/gic/v3/gicv3_main.c \ - drivers/arm/gic/common/gic_common.c \ +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +QEMU_GIC_SOURCES := ${GICV3_SOURCES} \ plat/common/plat_gicv3.c \ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c -BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \ - lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S \ +BL31_SOURCES += lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.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 \ + ${PLAT_QEMU_PATH}/sbsa_pm.c \ + ${PLAT_QEMU_PATH}/sbsa_topology.c \ ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \ ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \ + common/fdt_fixup.c \ + common/fdt_wrappers.c \ ${QEMU_GIC_SOURCES} +ifeq (${SPM_MM},1) + BL31_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_spm.c +endif SEPARATE_CODE_AND_RODATA := 1 ENABLE_STACK_PROTECTOR := 0 diff --git a/plat/qemu/qemu_sbsa/sbsa_pm.c b/plat/qemu/qemu_sbsa/sbsa_pm.c new file mode 100644 index 000000000..8d1e1d48c --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_pm.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <arch_helpers.h> +#include <assert.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/common/platform.h> + +#include <platform_def.h> +#include "sbsa_private.h" + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026 + +/* + * Define offset and commands for the fake EC device + */ +#define SBSA_SECURE_EC_OFFSET 0x50000000 + +#define SBSA_SECURE_EC_CMD_SHUTDOWN 0x01 +#define SBSA_SECURE_EC_CMD_REBOOT 0x02 + +/* + * The secure entry point to be used on warm reset. + */ +static unsigned long secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#else +#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#endif /* PSCI_EXTENDED_STATE_ID */ + + +#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + + + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int qemu_pm_idle_states[] = { + /* State-id - 0x01 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0 +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int qemu_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + unsigned int i; + + assert(req_state != NULL); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justifies the additional complexity. + */ + for (i = 0U; qemu_pm_idle_states[i] != 0U; i++) { + if (power_state == qemu_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (qemu_pm_idle_states[i] == 0U) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0U; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id != 0U) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void qemu_cpu_standby(plat_local_state_t cpu_state) +{ + + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int qemu_pwr_domain_on(u_register_t mpidr) +{ + int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; + + if (pos < 0) { + return PSCI_E_INVALID_PARAMS; + } + + hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; + dsb(); + sev(); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned off. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +static void qemu_pwr_domain_off(const psci_power_state_t *target_state) +{ + qemu_pwr_gic_off(); +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + disable_mmu_el3(); + plat_secondary_cold_boot_setup(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be suspended. The + * target_state encodes the power state that each level should transition to. + ******************************************************************************/ +void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); + + qemu_pwr_gic_on_finish(); +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + assert(false); +} + +/******************************************************************************* + * Platform handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 qemu_system_off(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_SHUTDOWN); + panic(); +} + +static void __dead2 qemu_system_reset(void) +{ + mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_REBOOT); + panic(); +} + +static const plat_psci_ops_t plat_qemu_psci_pm_ops = { + .cpu_standby = qemu_cpu_standby, + .pwr_domain_on = qemu_pwr_domain_on, + .pwr_domain_off = qemu_pwr_domain_off, + .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi, + .pwr_domain_suspend = qemu_pwr_domain_suspend, + .pwr_domain_on_finish = qemu_pwr_domain_on_finish, + .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, + .system_off = qemu_system_off, + .system_reset = qemu_system_reset, + .validate_power_state = qemu_validate_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (uintptr_t *)PLAT_QEMU_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (unsigned long)sec_entrypoint; + *psci_ops = &plat_qemu_psci_pm_ops; + + return 0; +} diff --git a/plat/qemu/qemu_sbsa/sbsa_private.h b/plat/qemu/qemu_sbsa/sbsa_private.h new file mode 100644 index 000000000..a9f4601de --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_private.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBSA_PRIVATE_H +#define SBSA_PRIVATE_H + +#include <stdint.h> + +unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + +void qemu_pwr_gic_on_finish(void); +void qemu_pwr_gic_off(void); + +#endif /* SBSA_PRIVATE_H */ diff --git a/plat/qemu/qemu_sbsa/sbsa_topology.c b/plat/qemu/qemu_sbsa/sbsa_topology.c new file mode 100644 index 000000000..bd8d16b9a --- /dev/null +++ b/plat/qemu/qemu_sbsa/sbsa_topology.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, Nuvia Inc + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <common/debug.h> + +#include <platform_def.h> +#include "sbsa_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[PLATFORM_CLUSTER_COUNT + 1]; + +/******************************************************************************* + * This function returns the sbsa-ref default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + unsigned int i; + + power_domain_tree_desc[0] = PLATFORM_CLUSTER_COUNT; + + for (i = 0U; i < PLATFORM_CLUSTER_COUNT; i++) { + power_domain_tree_desc[i + 1] = PLATFORM_MAX_CPUS_PER_CLUSTER; + } + + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { + ERROR("Invalid MPIDR\n"); + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + ERROR("cluster_id >= PLATFORM_CLUSTER_COUNT define\n"); + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + ERROR("cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER define\n"); + return -1; + } + + return plat_qemu_calc_core_pos(mpidr); +} |