/*
 * Copyright (c) 2023, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <stdio.h>

#include <arch_features.h>
#include <arch_helpers.h>
#include <debug.h>
#include <fpu.h>
#include <host_realm_helper.h>
#include <host_shared_data.h>
#include <psci.h>
#include "realm_def.h"
#include <realm_helpers.h>
#include <realm_psi.h>
#include <realm_rsi.h>
#include <realm_tests.h>
#include <realm_psci.h>
#include <tftf_lib.h>

#define CXT_ID_MAGIC	0x100
#define P1_CXT_ID_MAGIC	0x200

static uint64_t is_secondary_cpu_booted;
static spinlock_t lock;
static rsi_plane_run run[MAX_REC_COUNT] __aligned(PAGE_SIZE);
static u_register_t base, plane_index, perm_index;

static void plane0_recn_handler(u_register_t cxt_id)
{
	uint64_t rec = 0U;

	realm_printf("running on Rec= 0x%lx cxt_id= 0x%lx\n",
			read_mpidr_el1() & MPID_MASK, cxt_id);
	if (cxt_id < CXT_ID_MAGIC || cxt_id > CXT_ID_MAGIC + MAX_REC_COUNT) {
		realm_printf("Wrong cxt_id\n");
		rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
	}
	spin_lock(&lock);
	is_secondary_cpu_booted++;
	rec =  read_mpidr_el1() & MPID_MASK;
	spin_unlock(&lock);

	/* enter plane */
	u_register_t flags = 0U;

	/* Use Base adr, plane_index, perm_index programmed by P0 rec0 */
	run[rec].enter.pc = base;
	realm_printf("Entering plane %ld, ep=0x%lx rec=0x%lx\n", plane_index, base, rec);
	realm_plane_enter(plane_index, perm_index, base, flags, &run[rec]);

	if (run[rec].exit.gprs[0] == SMC_PSCI_CPU_OFF) {
		realm_printf("Plane N did not request CPU OFF\n");
		rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
	}
	realm_cpu_off();
}

static void recn_handler(u_register_t cxt_id)
{
	realm_printf("running on Rec= 0x%lx cxt_id= 0x%lx\n",
			read_mpidr_el1() & MPID_MASK, cxt_id);

	if (cxt_id < P1_CXT_ID_MAGIC || cxt_id > P1_CXT_ID_MAGIC + MAX_REC_COUNT) {
		realm_printf("Wrong cxt_id\n");
		rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
	}
	spin_lock(&lock);
	is_secondary_cpu_booted++;
	spin_unlock(&lock);
	realm_cpu_off();
}

static void rec2_handler(u_register_t cxt_id)
{
	rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
}

bool test_realm_multiple_rec_psci_denied_cmd(void)
{
	u_register_t ret;

	is_secondary_cpu_booted = 0U;
	ret = realm_cpu_on(1U, (uintptr_t)recn_handler, 0x100);
	if (ret != PSCI_E_DENIED) {
		return false;
	}

	if (is_secondary_cpu_booted != 0U) {
		rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
	}

	ret = realm_psci_affinity_info(1U, MPIDR_AFFLVL0);
	if (ret != PSCI_STATE_OFF) {
		realm_printf("CPU 1 should have been off\n");
		return false;
	}

	ret = realm_cpu_on(2U, (uintptr_t)rec2_handler, 0x102);
	if (ret != PSCI_E_ALREADY_ON) {
		realm_printf("CPU 2 should have been already on\n");
		return false;
	}
	return true;
}

/*
 * All Planes enter this test function.
 * P0 Rec0 Enters Plane N
 * Plane N rec 0 requests CPU ON for all other rec
 * P0 Rec0 requests CPU ON to host
 * Host enters P0 RecN from different CPU
 * P0 RecN enters PlaneN RecN
 * Rec N requests CPU OFF, exits to P0
 * P0 requests CPU OFF to host.
 * P0 verifies all other CPU are off.
 */
bool test_realm_multiple_plane_multiple_rec_multiple_cpu_cmd(void)
{
	unsigned int i = 1U, rec_count;
	u_register_t ret;
	bool ret1;

	realm_printf("Realm: running on Rec= 0x%lx\n", read_mpidr_el1() & MPID_MASK);
	rec_count = realm_shared_data_get_my_host_val(HOST_ARG3_INDEX);

	/* Check CPU_ON is supported */
	ret = realm_psci_features(SMC_PSCI_CPU_ON);
	if (ret != PSCI_E_SUCCESS) {
		realm_printf("SMC_PSCI_CPU_ON not supported\n");
		return false;
	}

	if (realm_is_plane0()) {
		/* Plane 0 all rec */
		u_register_t flags = 0U;

		plane_index = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
		base = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
		perm_index = plane_index + 1U;

		plane_common_init(plane_index, perm_index, base, &run[0U]);

		ret1 = realm_plane_enter(plane_index, perm_index, base, flags, &run[0U]);
		while (ret1 && run->exit.gprs[0] == SMC_PSCI_CPU_ON_AARCH64) {
			realm_printf("Plane N requested CPU on Rec=0x%lx\n", run[0].exit.gprs[1]);

			/* Pass context tp RecN - CXT + rec idx */
			run[0].enter.gprs[0] = realm_cpu_on(run[0].exit.gprs[1],
						(uintptr_t)plane0_recn_handler,
						CXT_ID_MAGIC + run[0].exit.gprs[1]);

			/* re-enter plane N 1 to complete cpu on */
			ret1 = realm_plane_enter(plane_index, perm_index, base, flags, &run[0U]);
			if (!ret1) {
				realm_printf("PlaneN CPU on complete failed\n");
				rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
			}
		}

		/* wait for all CPUs to come up */
		while (is_secondary_cpu_booted != rec_count - 1U) {
			waitms(200);
		}

		/* wait for all CPUs to turn off */
		while (i < rec_count) {
			ret = realm_psci_affinity_info(i, MPIDR_AFFLVL0);
			if (ret != PSCI_STATE_OFF) {
				/* wait and query again */
				realm_printf(" CPU %d is not off\n", i);
				waitms(200);
				continue;
			}
			i++;
		}
		realm_printf("All CPU are off\n");
		return true;
	} else {
		/* Plane 1 Rec 0 */
		for (unsigned int j = 1U; j < rec_count; j++) {
			realm_printf("CPU ON Rec=%u\n", j);
			ret = realm_cpu_on(j, (uintptr_t)recn_handler, P1_CXT_ID_MAGIC + j);
			if (ret != PSCI_E_SUCCESS) {
				realm_printf("SMC_PSCI_CPU_ON failed %d.\n", j);
				return false;
			}
		}
		/* Exit to Host to allow host to run all CPUs */
		rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);

		/* wait for all CPUs to come up */
		while (is_secondary_cpu_booted != rec_count - 1U) {
			waitms(200);
		}
		return true;
	}
	return true;
}

bool test_realm_multiple_rec_multiple_cpu_cmd(void)
{
	unsigned int i = 1U, rec_count;
	u_register_t ret;

	realm_printf("Realm: running on Rec= 0x%lx\n", read_mpidr_el1() & MPID_MASK);
	rec_count = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);

	/* Check CPU_ON is supported */
	ret = realm_psci_features(SMC_PSCI_CPU_ON);
	if (ret != PSCI_E_SUCCESS) {
		realm_printf("SMC_PSCI_CPU_ON not supported\n");
		return false;
	}

	for (unsigned int j = 1U; j < rec_count; j++) {
		ret = realm_cpu_on(j, (uintptr_t)recn_handler, P1_CXT_ID_MAGIC + j);
		if (ret != PSCI_E_SUCCESS) {
			realm_printf("SMC_PSCI_CPU_ON failed %d.\n", j);
			return false;
		}
	}

	/* Exit to host to allow host to run all CPUs */
	rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
	/* wait for all CPUs to come up */
	while (is_secondary_cpu_booted != rec_count - 1U) {
		waitms(200);
	}

	/* wait for all CPUs to turn off */
	while (i < rec_count) {
		ret = realm_psci_affinity_info(i, MPIDR_AFFLVL0);
		if (ret != PSCI_STATE_OFF) {
			/* wait and query again */
			realm_printf(" CPU %d is not off\n", i);
			waitms(200);
			continue;
		}
		i++;
	}
	realm_printf("All CPU are off\n");
	return true;
}
