diff options
-rw-r--r-- | bl32/sp_min/aarch32/entrypoint.S | 18 | ||||
-rw-r--r-- | docs/firmware-design.rst | 16 | ||||
-rw-r--r-- | docs/platform-migration-guide.rst | 11 | ||||
-rw-r--r-- | docs/porting-guide.rst | 38 | ||||
-rw-r--r-- | include/lib/aarch32/arch.h | 2 | ||||
-rw-r--r-- | include/lib/aarch32/smcc_helpers.h | 6 | ||||
-rw-r--r-- | include/lib/aarch32/smcc_macros.S | 12 | ||||
-rw-r--r-- | include/lib/aarch64/arch.h | 5 | ||||
-rw-r--r-- | include/lib/aarch64/arch_helpers.h | 2 | ||||
-rw-r--r-- | include/lib/el3_runtime/aarch64/context.h | 19 | ||||
-rw-r--r-- | include/lib/psci/psci.h | 14 | ||||
-rw-r--r-- | lib/el3_runtime/aarch64/context.S | 6 | ||||
-rw-r--r-- | lib/el3_runtime/aarch64/context_mgmt.c | 28 | ||||
-rw-r--r-- | lib/psci/psci_main.c | 7 | ||||
-rw-r--r-- | lib/psci/psci_private.h | 5 | ||||
-rw-r--r-- | lib/psci/psci_setup.c | 2 | ||||
-rw-r--r-- | lib/psci/psci_system_off.c | 30 | ||||
-rw-r--r-- | plat/arm/css/common/css_pm.c | 3 | ||||
-rw-r--r-- | plat/arm/css/drivers/scp/css_pm_scmi.c | 84 | ||||
-rw-r--r-- | plat/arm/css/drivers/scp/css_scp.h | 2 | ||||
-rw-r--r-- | tools/fiptool/fiptool.c | 15 | ||||
-rw-r--r-- | tools/fiptool/fiptool.h | 2 | ||||
-rw-r--r-- | tools/fiptool/fiptool_platform.h | 29 |
23 files changed, 285 insertions, 71 deletions
diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S index d868c53db..cd9fe5cb7 100644 --- a/bl32/sp_min/aarch32/entrypoint.S +++ b/bl32/sp_min/aarch32/entrypoint.S @@ -162,6 +162,15 @@ func handle_smc stcopr r0, SCR isb + /* + * Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode. + * Also, the PMCR.LC field has an architecturally UNKNOWN value on reset + * and so set to 1 as ARM has deprecated use of PMCR.LC=0. + */ + ldcopr r0, PMCR + orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT) + stcopr r0, PMCR + ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */ /* Check whether an SMC64 is issued */ tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT) @@ -210,6 +219,15 @@ func handle_fiq stcopr r0, SCR isb + /* + * Set PMCR.DP to 1 to prohibit cycle counting whilst in Secure Mode. + * Also, the PMCR.LC field has an architecturally UNKNOWN value on reset + * and so set to 1 as ARM has deprecated use of PMCR.LC=0. + */ + ldcopr r0, PMCR + orr r0, r0, #(PMCR_LC_BIT | PMCR_DP_BIT) + stcopr r0, PMCR + push {r2, r3} bl sp_min_fiq pop {r0, r3} diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index 6bbf12e02..e16e9b890 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -886,10 +886,10 @@ Power State Coordination Interface TODO: Provide design walkthrough of PSCI implementation. -The PSCI v1.0 specification categorizes APIs as optional and mandatory. All the -mandatory APIs in PSCI v1.0 and all the APIs in PSCI v0.2 draft specification +The PSCI v1.1 specification categorizes APIs as optional and mandatory. All the +mandatory APIs in PSCI v1.1, PSCI v1.0 and in PSCI v0.2 draft specification `Power State Coordination Interface PDD`_ are implemented. The table lists -the PSCI v1.0 APIs and their support in generic code. +the PSCI v1.1 APIs and their support in generic code. An API implementation might have a dependency on platform code e.g. CPU\_SUSPEND requires the platform to export a part of the implementation. Hence the level @@ -898,9 +898,9 @@ platform port as well. The Juno and FVP (all variants) platforms export all the required support. +-----------------------------+-------------+-------------------------------+ -| PSCI v1.0 API | Supported | Comments | +| PSCI v1.1 API | Supported | Comments | +=============================+=============+===============================+ -| ``PSCI_VERSION`` | Yes | The version returned is 1.0 | +| ``PSCI_VERSION`` | Yes | The version returned is 1.1 | +-----------------------------+-------------+-------------------------------+ | ``CPU_SUSPEND`` | Yes\* | | +-----------------------------+-------------+-------------------------------+ @@ -936,6 +936,12 @@ required support. +-----------------------------+-------------+-------------------------------+ | ``PSCI_STAT_COUNT`` | Yes\* | | +-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET2`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT_CHECK_RANGE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ \*Note : These PSCI APIs require platform power management hooks to be registered with the generic PSCI code to be supported. diff --git a/docs/platform-migration-guide.rst b/docs/platform-migration-guide.rst index 638033e44..ca7554693 100644 --- a/docs/platform-migration-guide.rst +++ b/docs/platform-migration-guide.rst @@ -158,6 +158,17 @@ for the ``plat_psci_ops`` structure which is declared as : int (*validate_ns_entrypoint)(unsigned long ns_entrypoint); void (*get_sys_suspend_power_state)( psci_power_state_t *req_state); + int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state, + int pwrlvl); + int (*translate_power_state_by_mpidr)(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state); + int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); + int (*mem_protect_chk)(uintptr_t base, u_register_t length); + int (*read_mem_protect)(int *val); + int (*write_mem_protect)(int val); + int (*system_reset2)(int is_vendor, + int reset_type, u_register_t cookie); } plat_psci_ops_t; The description of these handlers can be found in the `Porting Guide <porting-guide.rst#user-content-function--plat_setup_psci_ops-mandatory>`__. diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 6c07b2eb3..cd3bcdae4 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -2271,6 +2271,44 @@ appropriate. Implementations are not expected to handle ``power_levels`` greater than ``PLAT_MAX_PWR_LVL``. +plat\_psci\_ops.system\_reset2() +................................ + +This is an optional function. If implemented this function is +called during the ``SYSTEM_RESET2`` call to perform a reset +based on the first parameter ``reset_type`` as specified in +`PSCI`_. The parameter ``cookie`` can be used to pass additional +reset information. If the ``reset_type`` is not supported, the +function must return ``PSCI_E_NOT_SUPPORTED``. For architectural +resets, all failures must return ``PSCI_E_INVALID_PARAMETERS`` +and vendor reset can return other PSCI error codes as defined +in `PSCI`_. On success this function will not return. + +plat\_psci\_ops.write\_mem\_protect() +.................................... + +This is an optional function. If implemented it enables or disables the +``MEM_PROTECT`` functionality based on the value of ``val``. +A non-zero value enables ``MEM_PROTECT`` and a value of zero +disables it. Upon encountering failures it must return a negative value +and on success it must return 0. + +plat\_psci\_ops.read\_mem\_protect() +..................................... + +This is an optional function. If implemented it returns the current +state of ``MEM_PROTECT`` via the ``val`` parameter. Upon encountering +failures it must return a negative value and on success it must +return 0. + +plat\_psci\_ops.mem\_protect\_chk() +................................... + +This is an optional function. If implemented it checks if a memory +region defined by a base address ``base`` and with a size of ``length`` +bytes is protected by ``MEM_PROTECT``. If the region is protected +then it must return 0, otherwise it must return a negative number. + Interrupt Management framework (in BL31) ---------------------------------------- diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index 5fbb83a6c..6c6d6a1dc 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -350,6 +350,8 @@ #define PMCR_N_SHIFT 11 #define PMCR_N_MASK 0x1f #define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT) +#define PMCR_LC_BIT (1 << 6) +#define PMCR_DP_BIT (1 << 5) /******************************************************************************* * Definitions of register offsets, fields and macros for CPU system diff --git a/include/lib/aarch32/smcc_helpers.h b/include/lib/aarch32/smcc_helpers.h index 1bc843810..53f1aa4ab 100644 --- a/include/lib/aarch32/smcc_helpers.h +++ b/include/lib/aarch32/smcc_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,7 +21,8 @@ #define SMC_CTX_SP_MON 0x7C #define SMC_CTX_LR_MON 0x80 #define SMC_CTX_SCR 0x84 -#define SMC_CTX_SIZE 0x88 +#define SMC_CTX_PMCR 0x88 +#define SMC_CTX_SIZE 0x8C #ifndef __ASSEMBLY__ #include <cassert.h> @@ -73,6 +74,7 @@ typedef struct smc_ctx { u_register_t sp_mon; u_register_t lr_mon; u_register_t scr; + u_register_t pmcr; } smc_ctx_t; /* diff --git a/include/lib/aarch32/smcc_macros.S b/include/lib/aarch32/smcc_macros.S index 7edf41061..cf26175d6 100644 --- a/include/lib/aarch32/smcc_macros.S +++ b/include/lib/aarch32/smcc_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,6 +13,8 @@ * spsr, lr, sp registers and the `scr` register to the SMC context on entry * due a SMC call. The `lr` of the current mode (monitor) is expected to be * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. */ .macro smcc_save_gp_mode_regs /* Save r0 - r12 in the SMC context */ @@ -46,6 +48,8 @@ /* lr_mon is already saved by caller */ ldcopr r4, SCR str r4, [sp, #SMC_CTX_SCR] + ldcopr r4, PMCR + str r4, [sp, #SMC_CTX_PMCR] .endm /* @@ -70,6 +74,12 @@ stcopr r1, SCR isb + /* + * Restore the PMCR register. + */ + ldr r1, [r0, #SMC_CTX_PMCR] + stcopr r1, PMCR + /* Restore the banked registers including the current SPSR */ add r1, r0, #SMC_CTX_SP_USR ldm r1!, {r4-r12} diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index f85e78971..9cbe40587 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -502,9 +502,14 @@ #define CNTACR_RWPT_SHIFT U(0x5) /* PMCR_EL0 definitions */ +#define PMCR_EL0_RESET_VAL U(0x0) #define PMCR_EL0_N_SHIFT U(11) #define PMCR_EL0_N_MASK U(0x1f) #define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) +#define PMCR_EL0_LC_BIT (U(1) << 6) +#define PMCR_EL0_DP_BIT (U(1) << 5) +#define PMCR_EL0_X_BIT (U(1) << 4) +#define PMCR_EL0_D_BIT (U(1) << 3) /******************************************************************************* * Definitions of MAIR encodings for device and normal memory diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 0d0d7d335..684a0debb 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -307,7 +307,7 @@ DEFINE_SYSREG_READ_FUNC(ctr_el0) DEFINE_SYSREG_RW_FUNCS(mdcr_el2) DEFINE_SYSREG_RW_FUNCS(hstr_el2) DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) -DEFINE_SYSREG_READ_FUNC(pmcr_el0) +DEFINE_SYSREG_RW_FUNCS(pmcr_el0) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index dcbf1c9d4..a89468d49 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -87,22 +87,23 @@ #define CTX_AFSR1_EL1 U(0x98) #define CTX_CONTEXTIDR_EL1 U(0xa0) #define CTX_VBAR_EL1 U(0xa8) +#define CTX_PMCR_EL0 U(0xb0) /* * If the platform is AArch64-only, there is no need to save and restore these * AArch32 registers. */ #if CTX_INCLUDE_AARCH32_REGS -#define CTX_SPSR_ABT U(0xb0) -#define CTX_SPSR_UND U(0xb8) -#define CTX_SPSR_IRQ U(0xc0) -#define CTX_SPSR_FIQ U(0xc8) -#define CTX_DACR32_EL2 U(0xd0) -#define CTX_IFSR32_EL2 U(0xd8) -#define CTX_FP_FPEXC32_EL2 U(0xe0) -#define CTX_TIMER_SYSREGS_OFF U(0xf0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_ABT U(0xc0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_UND U(0xc8) +#define CTX_SPSR_IRQ U(0xd0) +#define CTX_SPSR_FIQ U(0xd8) +#define CTX_DACR32_EL2 U(0xe0) +#define CTX_IFSR32_EL2 U(0xe8) +#define CTX_FP_FPEXC32_EL2 U(0xf0) +#define CTX_TIMER_SYSREGS_OFF U(0x100) /* Align to the next 16 byte boundary */ #else -#define CTX_TIMER_SYSREGS_OFF U(0xb0) +#define CTX_TIMER_SYSREGS_OFF U(0xc0) /* Align to the next 16 byte boundary */ #endif /* __CTX_INCLUDE_AARCH32_REGS__ */ /* diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h index 0b44ab2e0..06434f9e5 100644 --- a/include/lib/psci/psci.h +++ b/include/lib/psci/psci.h @@ -65,6 +65,8 @@ #define PSCI_STAT_RESIDENCY_AARCH64 U(0xc4000010) #define PSCI_STAT_COUNT_AARCH32 U(0x84000011) #define PSCI_STAT_COUNT_AARCH64 U(0xc4000011) +#define PSCI_SYSTEM_RESET2_AARCH32 U(0x84000012) +#define PSCI_SYSTEM_RESET2_AARCH64 U(0xc4000012) #define PSCI_MEM_PROTECT U(0x84000013) #define PSCI_MEM_CHK_RANGE_AARCH32 U(0x84000014) #define PSCI_MEM_CHK_RANGE_AARCH64 U(0xc4000014) @@ -149,7 +151,7 @@ * PSCI version ******************************************************************************/ #define PSCI_MAJOR_VER (U(1) << 16) -#define PSCI_MINOR_VER U(0x0) +#define PSCI_MINOR_VER U(0x1) /******************************************************************************* * PSCI error codes @@ -167,6 +169,14 @@ #define PSCI_INVALID_MPIDR ~((u_register_t)0) +/* + * SYSTEM_RESET2 macros + */ +#define PSCI_RESET2_TYPE_VENDOR_SHIFT 31 +#define PSCI_RESET2_TYPE_VENDOR (1U << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_TYPE_ARCH (0U << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_SYSTEM_WARM_RESET (PSCI_RESET2_TYPE_ARCH | 0) + #ifndef __ASSEMBLY__ #include <stdint.h> @@ -294,6 +304,8 @@ typedef struct plat_psci_ops { int (*mem_protect_chk)(uintptr_t base, u_register_t length); int (*read_mem_protect)(int *val); int (*write_mem_protect)(int val); + int (*system_reset2)(int is_vendor, + int reset_type, u_register_t cookie); } plat_psci_ops_t; /******************************************************************************* diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 8a6c11b79..db16a9f0e 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -74,6 +74,9 @@ func el1_sysregs_context_save mrs x9, vbar_el1 stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + mrs x10, pmcr_el0 + str x10, [x0, #CTX_PMCR_EL0] + /* Save AArch32 system registers if the build has instructed so */ #if CTX_INCLUDE_AARCH32_REGS mrs x11, spsr_abt @@ -193,6 +196,9 @@ func el1_sysregs_context_restore msr contextidr_el1, x17 msr vbar_el1, x9 + ldr x10, [x0, #CTX_PMCR_EL0] + msr pmcr_el0, x10 + /* Restore AArch32 system registers if the build has instructed so */ #if CTX_INCLUDE_AARCH32_REGS ldp x11, x12, [x0, #CTX_SPSR_ABT] diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 3d26056a3..21e86de05 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -58,7 +58,7 @@ void cm_init(void) static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep) { unsigned int security_state; - uint32_t scr_el3; + uint32_t scr_el3, pmcr_el0; el3_state_t *state; gp_regs_t *gp_regs; unsigned long sctlr_elx; @@ -164,11 +164,35 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t /* * Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2 - * and other EL2 resgisters are set up by cm_preapre_ns_entry() as they + * and other EL2 registers are set up by cm_preapre_ns_entry() as they * are not part of the stored cpu_context. */ write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); + if (security_state == SECURE) { + /* + * Initialise PMCR_EL0 for secure context only, setting all + * fields rather than relying on hw. Some fields are + * architecturally UNKNOWN on reset. + * + * PMCR_EL0.LC: Set to one so that cycle counter overflow, that + * is recorded in PMOVSCLR_EL0[31], occurs on the increment + * that changes PMCCNTR_EL0[63] from 1 to 0. + * + * PMCR_EL0.DP: Set to one so that the cycle counter, + * PMCCNTR_EL0 does not count when event counting is prohibited. + * + * PMCR_EL0.X: Set to zero to disable export of events. + * + * PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0 + * counts on every clock cycle. + */ + pmcr_el0 = ((PMCR_EL0_RESET_VAL | PMCR_EL0_LC_BIT + | PMCR_EL0_DP_BIT) + & ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT)); + write_ctx_reg(get_sysregs_ctx(ctx), CTX_PMCR_EL0, pmcr_el0); + } + /* Populate EL3 state so that we've the right context before doing ERET */ state = get_el3state_ctx(ctx); write_ctx_reg(state, CTX_SCR_EL3, scr_el3); diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c index a5d707e01..4105e63bd 100644 --- a/lib/psci/psci_main.c +++ b/lib/psci/psci_main.c @@ -414,6 +414,10 @@ u_register_t psci_smc_handler(uint32_t smc_fid, case PSCI_MEM_CHK_RANGE_AARCH32: return psci_mem_chk_range(x1, x2); + case PSCI_SYSTEM_RESET2_AARCH32: + /* We should never return from psci_system_reset2() */ + return psci_system_reset2(x1, x2); + default: break; } @@ -453,6 +457,9 @@ u_register_t psci_smc_handler(uint32_t smc_fid, case PSCI_MEM_CHK_RANGE_AARCH64: return psci_mem_chk_range(x1, x2); + case PSCI_SYSTEM_RESET2_AARCH64: + /* We should never return from psci_system_reset2() */ + return psci_system_reset2(x1, x2); default: break; diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h index facfacb03..504fb9e4f 100644 --- a/lib/psci/psci_private.h +++ b/lib/psci/psci_private.h @@ -89,7 +89,9 @@ define_psci_cap(PSCI_NODE_HW_STATE_AARCH64) | \ define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \ define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \ - define_psci_cap(PSCI_STAT_COUNT_AARCH64)) + define_psci_cap(PSCI_STAT_COUNT_AARCH64) | \ + define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64) | \ + define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64)) /* * Helper macros to get/set the fields of PSCI per-cpu data. @@ -258,6 +260,7 @@ void psci_do_pwrup_cache_maintenance(void); /* Private exported functions from psci_system_off.c */ void __dead2 psci_system_off(void); void __dead2 psci_system_reset(void); +int psci_system_reset2(uint32_t reset_type, u_register_t cookie); /* Private exported functions from psci_stat.c */ void psci_stats_update_pwr_down(unsigned int end_pwrlvl, diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index 5ef49acbe..a841ddab9 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -248,6 +248,8 @@ int psci_setup(const psci_lib_args_t *lib_args) psci_caps |= define_psci_cap(PSCI_MEM_PROTECT); if (psci_plat_pm_ops->mem_protect_chk) psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64); + if (psci_plat_pm_ops->system_reset2) + psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64); #if ENABLE_PSCI_STAT psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64); diff --git a/lib/psci/psci_system_off.c b/lib/psci/psci_system_off.c index ef5d3d1d6..13e9f4aae 100644 --- a/lib/psci/psci_system_off.c +++ b/lib/psci/psci_system_off.c @@ -49,3 +49,33 @@ void __dead2 psci_system_reset(void) /* This function does not return. We should never get here */ } + +int psci_system_reset2(uint32_t reset_type, u_register_t cookie) +{ + int is_vendor; + + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_reset2); + + is_vendor = (reset_type >> PSCI_RESET2_TYPE_VENDOR_SHIFT) & 1; + if (!is_vendor) { + /* + * Only WARM_RESET is allowed for architectural type resets. + */ + if (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET) + return PSCI_E_INVALID_PARAMS; + if (psci_plat_pm_ops->write_mem_protect && + psci_plat_pm_ops->write_mem_protect(0) < 0) { + return PSCI_E_NOT_SUPPORTED; + } + } + + /* Notify the Secure Payload Dispatcher */ + if (psci_spd_pm && psci_spd_pm->svc_system_reset) { + psci_spd_pm->svc_system_reset(); + } + console_flush(); + + return psci_plat_pm_ops->system_reset2(is_vendor, reset_type, cookie); +} diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 93d51fe66..39c02aff2 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -300,4 +300,7 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .read_mem_protect = arm_psci_read_mem_protect, .write_mem_protect = arm_nor_psci_write_mem_protect, #endif +#if CSS_USE_SCMI_SDS_DRIVER + .system_reset2 = css_system_reset2, +#endif }; diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c index c39bc4ba7..e29cd8679 100644 --- a/plat/arm/css/drivers/scp/css_pm_scmi.c +++ b/plat/arm/css/drivers/scp/css_pm_scmi.c @@ -259,10 +259,7 @@ int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) return HW_OFF; } -/* - * Helper function to shutdown the system via SCMI. - */ -void __dead2 css_scp_sys_shutdown(void) +void __dead2 css_scp_system_off(int state) { int ret; @@ -273,52 +270,37 @@ void __dead2 css_scp_sys_shutdown(void) plat_arm_gic_cpuif_disable(); /* - * Issue SCMI command for SYSTEM_SHUTDOWN. First issue a graceful + * Issue SCMI command. First issue a graceful * request and if that fails force the request. */ ret = scmi_sys_pwr_state_set(scmi_handle, SCMI_SYS_PWR_FORCEFUL_REQ, - SCMI_SYS_PWR_SHUTDOWN); + state); + if (ret != SCMI_E_SUCCESS) { - ERROR("SCMI system power domain shutdown return 0x%x unexpected\n", - ret); + ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n", + state, ret); panic(); } - wfi(); - ERROR("CSS System Shutdown: operation not handled.\n"); + ERROR("CSS set power state: operation not handled.\n"); panic(); } /* + * Helper function to shutdown the system via SCMI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + css_scp_system_off(SCMI_SYS_PWR_SHUTDOWN); +} + +/* * Helper function to reset the system via SCMI. */ void __dead2 css_scp_sys_reboot(void) { - int ret; - - /* - * Disable GIC CPU interface to prevent pending interrupt from waking - * up the AP from WFI. - */ - plat_arm_gic_cpuif_disable(); - - /* - * Issue SCMI command for SYSTEM_REBOOT. First issue a graceful - * request and if that fails force the request. - */ - ret = scmi_sys_pwr_state_set(scmi_handle, - SCMI_SYS_PWR_FORCEFUL_REQ, - SCMI_SYS_PWR_COLD_RESET); - if (ret != SCMI_E_SUCCESS) { - ERROR("SCMI system power domain reset return 0x%x unexpected\n", - ret); - panic(); - } - - wfi(); - ERROR("CSS System Reset: operation not handled.\n"); - panic(); + css_scp_system_off(SCMI_SYS_PWR_COLD_RESET); } scmi_channel_plat_info_t plat_css_scmi_plat_info = { @@ -376,13 +358,35 @@ const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) ops->system_off = NULL; ops->system_reset = NULL; ops->get_sys_suspend_power_state = NULL; - } else if (!(msg_attr & SCMI_SYS_PWR_SUSPEND_SUPPORTED)) { - /* - * System power management protocol is available, but it does - * not support SYSTEM SUSPEND. - */ - ops->get_sys_suspend_power_state = NULL; + } else { + if (!(msg_attr & SCMI_SYS_PWR_SUSPEND_SUPPORTED)) { + /* + * System power management protocol is available, but + * it does not support SYSTEM SUSPEND. + */ + ops->get_sys_suspend_power_state = NULL; + } + if (!(msg_attr & SCMI_SYS_PWR_WARM_RESET_SUPPORTED)) { + /* + * WARM reset is not available. + */ + ops->system_reset2 = NULL; + } } return ops; } + +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie) +{ + if (is_vendor || (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET)) + return PSCI_E_INVALID_PARAMS; + + css_scp_system_off(SCMI_SYS_PWR_WARM_RESET); + /* + * css_scp_system_off cannot return (it is a __dead function), + * but css_system_reset2 has to return some value, even in + * this case. + */ + return 0; +} diff --git a/plat/arm/css/drivers/scp/css_scp.h b/plat/arm/css/drivers/scp/css_scp.h index 223e372a2..1f0cf8e24 100644 --- a/plat/arm/css/drivers/scp/css_scp.h +++ b/plat/arm/css/drivers/scp/css_scp.h @@ -15,12 +15,14 @@ struct psci_power_state; /* API for power management by SCP */ +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie); void css_scp_suspend(const struct psci_power_state *target_state); void css_scp_off(const struct psci_power_state *target_state); void css_scp_on(u_register_t mpidr); int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level); void __dead2 css_scp_sys_shutdown(void); void __dead2 css_scp_sys_reboot(void); +void __dead2 css_scp_system_off(int state); /* API for SCP Boot Image transfer. Return 0 on success, -1 on error */ int css_scp_boot_image_xfer(void *image, unsigned int image_size); diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c index 02223d991..1dcb7e8e6 100644 --- a/tools/fiptool/fiptool.c +++ b/tools/fiptool/fiptool.c @@ -9,18 +9,12 @@ #include <assert.h> #include <errno.h> -#include <getopt.h> #include <limits.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> - -#include <openssl/sha.h> - -#include <firmware_image_package.h> #include "fiptool.h" #include "tbbr_config.h" @@ -161,7 +155,7 @@ static void set_image_desc_action(image_desc_t *desc, int action, { assert(desc != NULL); - if (desc->action_arg != DO_UNSPEC) + if (desc->action_arg != (char *)DO_UNSPEC) free(desc->action_arg); desc->action = action; desc->action_arg = NULL; @@ -278,7 +272,7 @@ static void uuid_from_str(uuid_t *u, const char *s) static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) { - struct stat st; + struct BLD_PLAT_STAT st; FILE *fp; char *buf, *bufend; fip_toc_header_t *toc_header; @@ -370,11 +364,12 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) static image_t *read_image_from_file(const uuid_t *uuid, const char *filename) { - struct stat st; + struct BLD_PLAT_STAT st; image_t *image; FILE *fp; assert(uuid != NULL); + assert(filename != NULL); fp = fopen(filename, "rb"); if (fp == NULL) @@ -469,6 +464,7 @@ static int info_cmd(int argc, char *argv[]) (unsigned long long)image->toc_e.offset_address, (unsigned long long)image->toc_e.size, desc->cmdline_name); +#ifndef _MSC_VER /* We don't have SHA256 for Visual Studio. */ if (verbose) { unsigned char md[SHA256_DIGEST_LENGTH]; @@ -476,6 +472,7 @@ static int info_cmd(int argc, char *argv[]) printf(", sha256="); md_print(md, sizeof(md)); } +#endif putchar('\n'); } diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h index 4b5cdd91f..d8a5d2cae 100644 --- a/tools/fiptool/fiptool.h +++ b/tools/fiptool/fiptool.h @@ -13,6 +13,8 @@ #include <firmware_image_package.h> #include <uuid.h> +#include "fiptool_platform.h" + #define NELEM(x) (sizeof (x) / sizeof *(x)) enum { diff --git a/tools/fiptool/fiptool_platform.h b/tools/fiptool/fiptool_platform.h new file mode 100644 index 000000000..bfdd1efc3 --- /dev/null +++ b/tools/fiptool/fiptool_platform.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Build platform specific handling. + * This allows for builds on non-Posix platforms + * e.g. Visual Studio on Windows + */ + +#ifndef __FIPTOOL_PLATFORM_H__ +# define __FIPTOOL_PLATFORM_H__ + +# ifndef _MSC_VER + + /* Not Visual Studio, so include Posix Headers. */ +# include <getopt.h> +# include <openssl/sha.h> +# include <unistd.h> + +# define BLD_PLAT_STAT stat + +# else + + /* Visual Studio. */ + +# endif + +#endif /* __FIPTOOL_PLATFORM_H__ */ |