+/**
+ * prepare single target for restart
+ *
+ *
+ */
+static int aarch64_prepare_restart_one(struct target *target)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ int retval;
+ uint32_t dscr;
+ uint32_t tmp;
+
+ LOG_DEBUG("%s", target_name(target));
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if ((dscr & DSCR_ITE) == 0)
+ LOG_ERROR("DSCR.ITE must be set before leaving debug!");
+ if ((dscr & DSCR_ERR) != 0)
+ LOG_ERROR("DSCR.ERR must be cleared before leaving debug!");
+
+ /* acknowledge a pending CTI halt event */
+ retval = arm_cti_ack_events(armv8->cti, CTI_TRIG(HALT));
+ /*
+ * open the CTI gate for channel 1 so that the restart events
+ * get passed along to all PEs. Also close gate for channel 0
+ * to isolate the PE from halt events.
+ */
+ if (retval == ERROR_OK)
+ retval = arm_cti_ungate_channel(armv8->cti, 1);
+ if (retval == ERROR_OK)
+ retval = arm_cti_gate_channel(armv8->cti, 0);
+
+ /* make sure that DSCR.HDE is set */
+ if (retval == ERROR_OK) {
+ dscr |= DSCR_HDE;
+ retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, dscr);
+ }
+
+ if (retval == ERROR_OK) {
+ /* clear sticky bits in PRSR, SDR is now 0 */
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_PRSR, &tmp);
+ }
+
+ return retval;
+}
+
+static int aarch64_do_restart_one(struct target *target, enum restart_mode mode)
+{
+ struct armv8_common *armv8 = target_to_armv8(target);
+ int retval;
+
+ LOG_DEBUG("%s", target_name(target));
+
+ /* trigger an event on channel 1, generates a restart request to the PE */
+ retval = arm_cti_pulse_channel(armv8->cti, 1);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (mode == RESTART_SYNC) {
+ int64_t then = timeval_ms();
+ for (;;) {
+ int resumed;
+ /*
+ * if PRSR.SDR is set now, the target did restart, even
+ * if it's now already halted again (e.g. due to breakpoint)
+ */
+ retval = aarch64_check_state_one(target,
+ PRSR_SDR, PRSR_SDR, &resumed, NULL);
+ if (retval != ERROR_OK || resumed)
+ break;
+
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("%s: Timeout waiting for resume"PRIx32, target_name(target));
+ retval = ERROR_TARGET_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ target->debug_reason = DBG_REASON_NOTHALTED;
+ target->state = TARGET_RUNNING;
+
+ return ERROR_OK;
+}
+
+static int aarch64_restart_one(struct target *target, enum restart_mode mode)
+{
+ int retval;
+
+ LOG_DEBUG("%s", target_name(target));
+
+ retval = aarch64_prepare_restart_one(target);
+ if (retval == ERROR_OK)
+ retval = aarch64_do_restart_one(target, mode);
+
+ return retval;
+}
+
+/*
+ * prepare all but the current target for restart
+ */
+static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoints, struct target **p_first)
+{
+ int retval = ERROR_OK;
+ struct target_list *head;
+ struct target *first = NULL;
+ uint64_t address;
+
+ foreach_smp_target(head, target->head) {
+ struct target *curr = head->target;
+
+ /* skip calling target */
+ if (curr == target)
+ continue;
+ if (!target_was_examined(curr))
+ continue;
+ if (curr->state != TARGET_HALTED)
+ continue;
+
+ /* resume at current address, not in step mode */
+ retval = aarch64_restore_one(curr, 1, &address, handle_breakpoints, 0);
+ if (retval == ERROR_OK)
+ retval = aarch64_prepare_restart_one(curr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("failed to restore target %s", target_name(curr));
+ break;
+ }
+ /* remember the first valid target in the group */
+ if (first == NULL)
+ first = curr;
+ }
+
+ if (p_first)
+ *p_first = first;
+
+ return retval;
+}
+
+
+static int aarch64_step_restart_smp(struct target *target)
+{
+ int retval = ERROR_OK;
+ struct target_list *head;
+ struct target *first = NULL;
+
+ LOG_DEBUG("%s", target_name(target));