diff options
author | Soby Mathew <soby.mathew@arm.com> | 2014-10-23 10:35:34 +0100 |
---|---|---|
committer | Dan Handley <dan.handley@arm.com> | 2015-01-26 12:42:45 +0000 |
commit | 8991eed7439cb565da505a2bf88e9ac87ad79c1c (patch) | |
tree | 7f9294e7e79f337eeafd725c520ac3cd8c083a83 | |
parent | 860331aa15ab251c515c396a5c095662de4ae5e6 (diff) |
Rework the PSCI migrate APIs
This patch reworks the PSCI MIGRATE, MIGRATE_INFO_TYPE and
MIGRATE_INFO_UP_CPU support for Trusted Firmware. The
implementation does the appropriate validation of parameters
and invokes the appropriate hook exported by the SPD.
The TSP is a MP Trusted OS. Hence the ability to actually
migrate a Trusted OS has not been implemented. The
corresponding function is not populated in the spd_pm_hooks
structure for the TSPD.
The `spd_pm_ops_t` has undergone changes with this patch.
SPD PORTS MAY NEED TO BE UPDATED.
Fixes ARM-software/tf-issues#249
Change-Id: Iabd87521bf7c530a5e4506b6d3bfd4f1bf87604f
-rw-r--r-- | include/bl31/services/psci.h | 10 | ||||
-rw-r--r-- | services/std_svc/psci/psci_common.c | 23 | ||||
-rw-r--r-- | services/std_svc/psci/psci_main.c | 52 | ||||
-rw-r--r-- | services/std_svc/psci/psci_private.h | 1 |
4 files changed, 71 insertions, 15 deletions
diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h index 3804bf2c..de6fe4b8 100644 --- a/include/bl31/services/psci.h +++ b/include/bl31/services/psci.h @@ -191,8 +191,8 @@ typedef struct spd_pm_ops { void (*svc_suspend)(uint64_t __unused); void (*svc_on_finish)(uint64_t __unused); void (*svc_suspend_finish)(uint64_t suspend_level); - void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2); - int32_t (*svc_migrate_info)(uint64_t *__unused); + int32_t (*svc_migrate)(uint64_t from_cpu, uint64_t to_cpu); + int32_t (*svc_migrate_info)(uint64_t *resident_cpu); void (*svc_system_off)(void); void (*svc_system_reset)(void); } spd_pm_ops_t; @@ -202,9 +202,9 @@ typedef struct spd_pm_ops { ******************************************************************************/ unsigned int psci_version(void); int psci_affinity_info(unsigned long, unsigned int); -int psci_migrate(unsigned int); -unsigned int psci_migrate_info_type(void); -unsigned long psci_migrate_info_up_cpu(void); +int psci_migrate(unsigned long); +int psci_migrate_info_type(void); +long psci_migrate_info_up_cpu(void); int psci_cpu_on(unsigned long, unsigned long, unsigned long); diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c index d8c8618f..898a343d 100644 --- a/services/std_svc/psci/psci_common.c +++ b/services/std_svc/psci/psci_common.c @@ -562,6 +562,29 @@ void psci_register_spd_pm_hook(const spd_pm_ops_t *pm) } /******************************************************************************* + * This function invokes the migrate info hook in the spd_pm_ops. It performs + * the necessary return value validation. If the Secure Payload is UP and + * migrate capable, it returns the mpidr of the CPU on which the Secure payload + * is resident through the mpidr parameter. Else the value of the parameter on + * return is undefined. + ******************************************************************************/ +int psci_spd_migrate_info(uint64_t *mpidr) +{ + int rc; + + if (!psci_spd_pm || !psci_spd_pm->svc_migrate_info) + return PSCI_E_NOT_SUPPORTED; + + rc = psci_spd_pm->svc_migrate_info(mpidr); + + assert(rc == PSCI_TOS_UP_MIG_CAP || rc == PSCI_TOS_NOT_UP_MIG_CAP \ + || rc == PSCI_TOS_NOT_PRESENT_MP || rc == PSCI_E_NOT_SUPPORTED); + + return rc; +} + + +/******************************************************************************* * This function prints the state of all affinity instances present in the * system ******************************************************************************/ diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c index 91d16f46..af00551e 100644 --- a/services/std_svc/psci/psci_main.c +++ b/services/std_svc/psci/psci_main.c @@ -219,25 +219,57 @@ int psci_affinity_info(unsigned long target_affinity, return rc; } -/* Unimplemented */ -int psci_migrate(unsigned int target_cpu) +int psci_migrate(unsigned long target_cpu) { - return PSCI_E_NOT_SUPPORTED; + int rc; + unsigned long resident_cpu_mpidr; + + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if (rc != PSCI_TOS_UP_MIG_CAP) + return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ? + PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED; + + /* + * Migrate should only be invoked on the CPU where + * the Secure OS is resident. + */ + if (resident_cpu_mpidr != read_mpidr_el1()) + return PSCI_E_NOT_PRESENT; + + /* Check the validity of the specified target cpu */ + rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + assert(psci_spd_pm && psci_spd_pm->svc_migrate); + + rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu); + assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL); + + return rc; } -/* Unimplemented */ -unsigned int psci_migrate_info_type(void) +int psci_migrate_info_type(void) { - return PSCI_TOS_NOT_PRESENT_MP; + unsigned long resident_cpu_mpidr; + + return psci_spd_migrate_info(&resident_cpu_mpidr); } -unsigned long psci_migrate_info_up_cpu(void) +long psci_migrate_info_up_cpu(void) { + unsigned long resident_cpu_mpidr; + int rc; + /* - * Return value of this currently unsupported call depends upon - * what psci_migrate_info_type() returns. + * Return value of this depends upon what + * psci_spd_migrate_info() returns. */ - return PSCI_E_SUCCESS; + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if (rc != PSCI_TOS_NOT_UP_MIG_CAP && rc != PSCI_TOS_UP_MIG_CAP) + return PSCI_E_INVALID_PARAMS; + + return resident_cpu_mpidr; } /******************************************************************************* diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h index 4fc87217..62477702 100644 --- a/services/std_svc/psci/psci_private.h +++ b/services/std_svc/psci/psci_private.h @@ -120,6 +120,7 @@ void psci_set_max_phys_off_afflvl(uint32_t afflvl); uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl, uint32_t end_afflvl, aff_map_node_t *mpidr_nodes[]); +int psci_spd_migrate_info(uint64_t *mpidr); /* Private exported functions from psci_setup.c */ int psci_get_aff_map_nodes(unsigned long mpidr, |