/*
 * QEMU support -- ARM Power Control specific functions.
 *
 * Copyright (c) 2016 Jean-Christophe Dubois
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "cpu.h"
#include "cpu-qom.h"
#include "internals.h"
#include "arm-powerctl.h"
#include "qemu/log.h"
#include "exec/exec-all.h"

#ifndef DEBUG_ARM_POWERCTL
#define DEBUG_ARM_POWERCTL 0
#endif

#define DPRINTF(fmt, args...) \
    do { \
        if (DEBUG_ARM_POWERCTL) { \
            fprintf(stderr, "[ARM]%s: " fmt , __func__, ##args); \
        } \
    } while (0)

CPUState *arm_get_cpu_by_id(uint64_t id)
{
    CPUState *cpu;

    DPRINTF("cpu %" PRId64 "\n", id);

    CPU_FOREACH(cpu) {
        ARMCPU *armcpu = ARM_CPU(cpu);

        if (armcpu->mp_affinity == id) {
            return cpu;
        }
    }

    qemu_log_mask(LOG_GUEST_ERROR,
                  "[ARM]%s: Requesting unknown CPU %" PRId64 "\n",
                  __func__, id);

    return NULL;
}

int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id,
                   uint32_t target_el, bool target_aa64)
{
    CPUState *target_cpu_state;
    ARMCPU *target_cpu;

    DPRINTF("cpu %" PRId64 " (EL %d, %s) @ 0x%" PRIx64 " with R0 = 0x%" PRIx64
            "\n", cpuid, target_el, target_aa64 ? "aarch64" : "aarch32", entry,
            context_id);

    /* requested EL level need to be in the 1 to 3 range */
    assert((target_el > 0) && (target_el < 4));

    if (target_aa64 && (entry & 3)) {
        /*
         * if we are booting in AArch64 mode then "entry" needs to be 4 bytes
         * aligned.
         */
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }

    /* Retrieve the cpu we are powering up */
    target_cpu_state = arm_get_cpu_by_id(cpuid);
    if (!target_cpu_state) {
        /* The cpu was not found */
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }

    target_cpu = ARM_CPU(target_cpu_state);
    if (!target_cpu->powered_off) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "[ARM]%s: CPU %" PRId64 " is already on\n",
                      __func__, cpuid);
        return QEMU_ARM_POWERCTL_ALREADY_ON;
    }

    /*
     * The newly brought CPU is requested to enter the exception level
     * "target_el" and be in the requested mode (AArch64 or AArch32).
     */

    if (((target_el == 3) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) ||
        ((target_el == 2) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL2))) {
        /*
         * The CPU does not support requested level
         */
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }

    if (!target_aa64 && arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64)) {
        /*
         * For now we don't support booting an AArch64 CPU in AArch32 mode
         * TODO: We should add this support later
         */
        qemu_log_mask(LOG_UNIMP,
                      "[ARM]%s: Starting AArch64 CPU %" PRId64
                      " in AArch32 mode is not supported yet\n",
                      __func__, cpuid);
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }

    /* Initialize the cpu we are turning on */
    cpu_reset(target_cpu_state);
    target_cpu->powered_off = false;
    target_cpu_state->halted = 0;

    if (target_aa64) {
        if ((target_el < 3) && arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) {
            /*
             * As target mode is AArch64, we need to set lower
             * exception level (the requested level 2) to AArch64
             */
            target_cpu->env.cp15.scr_el3 |= SCR_RW;
        }

        if ((target_el < 2) && arm_feature(&target_cpu->env, ARM_FEATURE_EL2)) {
            /*
             * As target mode is AArch64, we need to set lower
             * exception level (the requested level 1) to AArch64
             */
            target_cpu->env.cp15.hcr_el2 |= HCR_RW;
        }

        target_cpu->env.pstate = aarch64_pstate_mode(target_el, true);
    } else {
        /* We are requested to boot in AArch32 mode */
        static uint32_t mode_for_el[] = { 0,
                                          ARM_CPU_MODE_SVC,
                                          ARM_CPU_MODE_HYP,
                                          ARM_CPU_MODE_SVC };

        cpsr_write(&target_cpu->env, mode_for_el[target_el], CPSR_M,
                   CPSRWriteRaw);
    }

    if (target_el == 3) {
        /* Processor is in secure mode */
        target_cpu->env.cp15.scr_el3 &= ~SCR_NS;
    } else {
        /* Processor is not in secure mode */
        target_cpu->env.cp15.scr_el3 |= SCR_NS;
    }

    /* We check if the started CPU is now at the correct level */
    assert(target_el == arm_current_el(&target_cpu->env));

    if (target_aa64) {
        target_cpu->env.xregs[0] = context_id;
        target_cpu->env.thumb = false;
    } else {
        target_cpu->env.regs[0] = context_id;
        target_cpu->env.thumb = entry & 1;
        entry &= 0xfffffffe;
    }

    /* Start the new CPU at the requested address */
    cpu_set_pc(target_cpu_state, entry);

    qemu_cpu_kick(target_cpu_state);

    /* We are good to go */
    return QEMU_ARM_POWERCTL_RET_SUCCESS;
}

int arm_set_cpu_off(uint64_t cpuid)
{
    CPUState *target_cpu_state;
    ARMCPU *target_cpu;

    DPRINTF("cpu %" PRId64 "\n", cpuid);

    /* change to the cpu we are powering up */
    target_cpu_state = arm_get_cpu_by_id(cpuid);
    if (!target_cpu_state) {
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }
    target_cpu = ARM_CPU(target_cpu_state);
    if (target_cpu->powered_off) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "[ARM]%s: CPU %" PRId64 " is already off\n",
                      __func__, cpuid);
        return QEMU_ARM_POWERCTL_IS_OFF;
    }

    target_cpu->powered_off = true;
    target_cpu_state->halted = 1;
    target_cpu_state->exception_index = EXCP_HLT;
    cpu_loop_exit(target_cpu_state);
    /* notreached */

    return QEMU_ARM_POWERCTL_RET_SUCCESS;
}

int arm_reset_cpu(uint64_t cpuid)
{
    CPUState *target_cpu_state;
    ARMCPU *target_cpu;

    DPRINTF("cpu %" PRId64 "\n", cpuid);

    /* change to the cpu we are resetting */
    target_cpu_state = arm_get_cpu_by_id(cpuid);
    if (!target_cpu_state) {
        return QEMU_ARM_POWERCTL_INVALID_PARAM;
    }
    target_cpu = ARM_CPU(target_cpu_state);
    if (target_cpu->powered_off) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "[ARM]%s: CPU %" PRId64 " is off\n",
                      __func__, cpuid);
        return QEMU_ARM_POWERCTL_IS_OFF;
    }

    /* Reset the cpu */
    cpu_reset(target_cpu_state);

    return QEMU_ARM_POWERCTL_RET_SUCCESS;
}
