feat(psci): make pabandon support generic

Support for aborted powerdowns does not require much dedicated code.
Rather, it is largely a matter of orchestrating things to happen in the
right order.

The only exception to this are older secure world dispatchers, which
assume that a CPU_SUSPEND call will be terminal and therefore can
clobber context. This was patched over in common code and hidden behind
a flag. This patch moves this to the dispatchers themselves.

Dispatchers that don't register svc_suspend{_finish} are unaffected.
Those that do must save the NS context before clobbering it and
restoring in only in case of a pabandon. Due to this operation being
non-trivial, this patch makes the assumption that these dispatchers will
only be present on hardware that does not support pabandon and therefore
does not add any contexting for them. In case this assumption ever
changes, asserts are added that should alert us of this change.

Change-Id: I94a907515b782b4d2136c0d274246cfe1d567c0e
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 15a32f1..04917ea 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1056,7 +1056,7 @@
 		unsigned int max_off_lvl = psci_find_max_off_lvl(&state_info);
 
 		assert(max_off_lvl != PSCI_INVALID_PWR_LVL);
-		psci_cpu_suspend_to_powerdown_finish(cpu_idx, max_off_lvl, &state_info);
+		psci_cpu_suspend_to_powerdown_finish(cpu_idx, max_off_lvl, &state_info, false);
 	}
 
 	/*
@@ -1311,15 +1311,13 @@
 
 	/*
 	 * Waking up does not require hardware-assisted coherency, but that is
-	 * the case for every core that can wake up. Untangling the cache
-	 * coherency code from powerdown is a non-trivial effort which isn't
-	 * needed for our purposes.
+	 * the case for every core that can wake up. Can either happen because
+	 * of errata or pabandon.
 	 */
-#if !FEAT_PABANDON || !defined(__aarch64__)
-	ERROR("Systems without FEAT_PABANDON shouldn't wake up.\n");
+#if !defined(__aarch64__) || !HW_ASSISTED_COHERENCY
+	ERROR("AArch32 systems shouldn't wake up.\n");
 	panic();
-#else /* FEAT_PABANDON */
-
+#endif
 	/*
 	 * Begin unwinding. Everything can be shared with CPU_ON and co later,
 	 * except the CPU specific bit. Cores that have hardware-assisted
@@ -1327,7 +1325,6 @@
 	 * the simplest way to achieve this
 	 */
 	prepare_cpu_pwr_dwn(power_level);
-#endif /* FEAT_PABANDON */
 }
 
 /*******************************************************************************
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index d4c6415..446f23d 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -341,7 +341,10 @@
 			   psci_power_state_t *state_info,
 			   unsigned int is_power_down_state);
 
-void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, unsigned int max_off_lvl, const psci_power_state_t *state_info);
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx,
+					  unsigned int max_off_lvl,
+					  const psci_power_state_t *state_info,
+					  bool abandon);
 
 /* Private exported functions from psci_helpers.S */
 void psci_do_pwrdown_cache_maintenance(void);
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 73b9a67..3b0364c 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -184,17 +184,6 @@
 #endif
 
 	if (is_power_down_state != 0U) {
-		/*
-		 * WHen CTX_INCLUDE_EL2_REGS is usnet, we're probably runnig
-		 * with some SPD that assumes the core is going off so it
-		 * doesn't bother saving NS's context. Do that here until we
-		 * figure out a way to make this coherent.
-		 */
-#if FEAT_PABANDON
-#if !CTX_INCLUDE_EL2_REGS
-		cm_el1_sysregs_context_save(NON_SECURE);
-#endif
-#endif
 		max_off_lvl = psci_find_max_off_lvl(state_info);
 		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, state_info);
 	}
@@ -274,13 +263,7 @@
 	 * the system back to a usable state.
 	 */
 	if (is_power_down_state != 0U) {
-#if FEAT_PABANDON
-		psci_cpu_suspend_to_powerdown_finish(idx, max_off_lvl, state_info);
-
-#if !CTX_INCLUDE_EL2_REGS
-		cm_el1_sysregs_context_restore(NON_SECURE);
-#endif
-#endif
+		psci_cpu_suspend_to_powerdown_finish(idx, max_off_lvl, state_info, true);
 	} else {
 		psci_cpu_suspend_to_standby_finish(end_pwrlvl, state_info);
 	}
@@ -307,7 +290,7 @@
  * are called by the common finisher routine in psci_common.c. The `state_info`
  * is the psci_power_state from which this CPU has woken up from.
  ******************************************************************************/
-void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, unsigned int max_off_lvl, const psci_power_state_t *state_info)
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, unsigned int max_off_lvl, const psci_power_state_t *state_info, bool abandon)
 {
 	unsigned int counter_freq;
 
@@ -345,7 +328,7 @@
 	 * error, it's expected to assert within
 	 */
 	if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend_finish != NULL)) {
-		psci_spd_pm->svc_suspend_finish(max_off_lvl);
+		psci_spd_pm->svc_suspend_finish(max_off_lvl, abandon);
 	}
 
 	/* This loses its meaning when not suspending, reset so it's correct for OFF */