/*
 * QEMU CPU QMP commands for RISC-V
 *
 * Copyright (c) 2023 Ventana Micro Systems Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "qemu/osdep.h"

#include "qapi/error.h"
#include "qapi/qapi-commands-machine-target.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/visitor.h"
#include "qom/qom-qobject.h"
#include "sysemu/kvm.h"
#include "sysemu/tcg.h"
#include "cpu-qom.h"
#include "cpu.h"

static void riscv_cpu_add_definition(gpointer data, gpointer user_data)
{
    ObjectClass *oc = data;
    CpuDefinitionInfoList **cpu_list = user_data;
    CpuDefinitionInfo *info = g_malloc0(sizeof(*info));
    const char *typename = object_class_get_name(oc);
    ObjectClass *dyn_class;

    info->name = cpu_model_from_type(typename);
    info->q_typename = g_strdup(typename);

    dyn_class = object_class_dynamic_cast(oc, TYPE_RISCV_DYNAMIC_CPU);
    info->q_static = dyn_class == NULL;

    QAPI_LIST_PREPEND(*cpu_list, info);
}

CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
    CpuDefinitionInfoList *cpu_list = NULL;
    GSList *list = object_class_get_list(TYPE_RISCV_CPU, false);

    g_slist_foreach(list, riscv_cpu_add_definition, &cpu_list);
    g_slist_free(list);

    return cpu_list;
}

static void riscv_check_if_cpu_available(RISCVCPU *cpu, Error **errp)
{
    if (!riscv_cpu_accelerator_compatible(cpu)) {
        g_autofree char *name = riscv_cpu_get_name(cpu);
        const char *accel = kvm_enabled() ? "kvm" : "tcg";

        error_setg(errp, "'%s' CPU not available with %s", name, accel);
        return;
    }
}

static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out,
                                     const char *name)
{
    ObjectProperty *prop = object_property_find(obj, name);

    if (prop) {
        QObject *value;

        assert(prop->get);
        value = object_property_get_qobject(obj, name, &error_abort);

        qdict_put_obj(qdict_out, name, value);
    }
}

static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out,
                                         const RISCVCPUMultiExtConfig *arr)
{
    for (int i = 0; arr[i].name != NULL; i++) {
        riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name);
    }
}

static void riscv_obj_add_named_feats_qdict(Object *obj, QDict *qdict_out)
{
    const RISCVCPUMultiExtConfig *named_cfg;
    RISCVCPU *cpu = RISCV_CPU(obj);
    QObject *value;
    bool flag_val;

    for (int i = 0; riscv_cpu_named_features[i].name != NULL; i++) {
        named_cfg = &riscv_cpu_named_features[i];
        flag_val = isa_ext_is_enabled(cpu, named_cfg->offset);
        value = QOBJECT(qbool_from_bool(flag_val));

        qdict_put_obj(qdict_out, named_cfg->name, value);
    }
}

static void riscv_obj_add_profiles_qdict(Object *obj, QDict *qdict_out)
{
    RISCVCPUProfile *profile;
    QObject *value;

    for (int i = 0; riscv_profiles[i] != NULL; i++) {
        profile = riscv_profiles[i];
        value = QOBJECT(qbool_from_bool(profile->enabled));

        qdict_put_obj(qdict_out, profile->name, value);
    }
}

static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props,
                                           const QDict *qdict_in,
                                           Error **errp)
{
    const QDictEntry *qe;
    Visitor *visitor;
    Error *local_err = NULL;

    visitor = qobject_input_visitor_new(props);
    if (!visit_start_struct(visitor, NULL, NULL, 0, &local_err)) {
        goto err;
    }

    for (qe = qdict_first(qdict_in); qe; qe = qdict_next(qdict_in, qe)) {
        object_property_find_err(obj, qe->key, &local_err);
        if (local_err) {
            goto err;
        }

        object_property_set(obj, qe->key, visitor, &local_err);
        if (local_err) {
            goto err;
        }
    }

    visit_check_struct(visitor, &local_err);
    if (local_err) {
        goto err;
    }

    visit_end_struct(visitor, NULL);

err:
    error_propagate(errp, local_err);
    visit_free(visitor);
}

CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
                                                     CpuModelInfo *model,
                                                     Error **errp)
{
    CpuModelExpansionInfo *expansion_info;
    const QDict *qdict_in = NULL;
    QDict *qdict_out;
    ObjectClass *oc;
    Object *obj;
    Error *local_err = NULL;

    if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
        error_setg(errp, "The requested expansion type is not supported");
        return NULL;
    }

    oc = cpu_class_by_name(TYPE_RISCV_CPU, model->name);
    if (!oc) {
        error_setg(errp, "The CPU type '%s' is not a known RISC-V CPU type",
                   model->name);
        return NULL;
    }

    if (model->props) {
        qdict_in = qobject_to(QDict, model->props);
        if (!qdict_in) {
            error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
            return NULL;
        }
    }

    obj = object_new(object_class_get_name(oc));

    riscv_check_if_cpu_available(RISCV_CPU(obj), &local_err);
    if (local_err != NULL) {
        error_propagate(errp, local_err);
        object_unref(obj);
        return NULL;
    }

    if (qdict_in) {
        riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in,
                                       &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
            object_unref(obj);
            return NULL;
        }
    }

    riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        object_unref(obj);
        return NULL;
    }

    expansion_info = g_new0(CpuModelExpansionInfo, 1);
    expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
    expansion_info->model->name = g_strdup(model->name);

    qdict_out = qdict_new();

    riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions);
    riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts);
    riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts);
    riscv_obj_add_named_feats_qdict(obj, qdict_out);
    riscv_obj_add_profiles_qdict(obj, qdict_out);

    /* Add our CPU boolean options too */
    riscv_obj_add_qdict_prop(obj, qdict_out, "mmu");
    riscv_obj_add_qdict_prop(obj, qdict_out, "pmp");

    if (!qdict_size(qdict_out)) {
        qobject_unref(qdict_out);
    } else {
        expansion_info->model->props = QOBJECT(qdict_out);
    }

    object_unref(obj);

    return expansion_info;
}
