Merge pull request #1127 from davidcunado-arm/dc/pmrc_init
Init and save / restore of PMCR_EL0 / PMCR
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 997d29b..f28d2f6 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -886,10 +886,10 @@
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 @@
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 @@
+-----------------------------+-------------+-------------------------------+
| ``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 638033e..ca75546 100644
--- a/docs/platform-migration-guide.rst
+++ b/docs/platform-migration-guide.rst
@@ -158,6 +158,17 @@
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 6c07b2e..cd3bcda 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2271,6 +2271,44 @@
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/psci/psci.h b/include/lib/psci/psci.h
index 0b44ab2..06434f9 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 @@
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/psci/psci_main.c b/lib/psci/psci_main.c
index a5d707e..4105e63 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -414,6 +414,10 @@
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 @@
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 facfacb..504fb9e 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 @@
/* 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 5ef49ac..a841dda 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -248,6 +248,8 @@
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 ef5d3d1..13e9f4a 100644
--- a/lib/psci/psci_system_off.c
+++ b/lib/psci/psci_system_off.c
@@ -49,3 +49,33 @@
/* 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 93d51fe..39c02af 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -300,4 +300,7 @@
.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 c39bc4b..e29cd86 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 @@
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 @@
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 @@
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 223e372..1f0cf8e 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 02223d9..1dcb7e8 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 @@
{
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 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 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 @@
(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 @@
printf(", sha256=");
md_print(md, sizeof(md));
}
+#endif
putchar('\n');
}
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index 4b5cdd9..d8a5d2c 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 0000000..bfdd1ef
--- /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__ */