/*
 * QEMU RISC-V NUMA Helper
 *
 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2 or later, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
#include "hw/riscv/numa.h"
#include "sysemu/device_tree.h"

static bool numa_enabled(const MachineState *ms)
{
    return (ms->numa_state && ms->numa_state->num_nodes) ? true : false;
}

int riscv_socket_count(const MachineState *ms)
{
    return (numa_enabled(ms)) ? ms->numa_state->num_nodes : 1;
}

int riscv_socket_first_hartid(const MachineState *ms, int socket_id)
{
    int i, first_hartid = ms->smp.cpus;

    if (!numa_enabled(ms)) {
        return (!socket_id) ? 0 : -1;
    }

    for (i = 0; i < ms->smp.cpus; i++) {
        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
            continue;
        }
        if (i < first_hartid) {
            first_hartid = i;
        }
    }

    return (first_hartid < ms->smp.cpus) ? first_hartid : -1;
}

int riscv_socket_last_hartid(const MachineState *ms, int socket_id)
{
    int i, last_hartid = -1;

    if (!numa_enabled(ms)) {
        return (!socket_id) ? ms->smp.cpus - 1 : -1;
    }

    for (i = 0; i < ms->smp.cpus; i++) {
        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
            continue;
        }
        if (i > last_hartid) {
            last_hartid = i;
        }
    }

    return (last_hartid < ms->smp.cpus) ? last_hartid : -1;
}

int riscv_socket_hart_count(const MachineState *ms, int socket_id)
{
    int first_hartid, last_hartid;

    if (!numa_enabled(ms)) {
        return (!socket_id) ? ms->smp.cpus : -1;
    }

    first_hartid = riscv_socket_first_hartid(ms, socket_id);
    if (first_hartid < 0) {
        return -1;
    }

    last_hartid = riscv_socket_last_hartid(ms, socket_id);
    if (last_hartid < 0) {
        return -1;
    }

    if (first_hartid > last_hartid) {
        return -1;
    }

    return last_hartid - first_hartid + 1;
}

bool riscv_socket_check_hartids(const MachineState *ms, int socket_id)
{
    int i, first_hartid, last_hartid;

    if (!numa_enabled(ms)) {
        return (!socket_id) ? true : false;
    }

    first_hartid = riscv_socket_first_hartid(ms, socket_id);
    if (first_hartid < 0) {
        return false;
    }

    last_hartid = riscv_socket_last_hartid(ms, socket_id);
    if (last_hartid < 0) {
        return false;
    }

    for (i = first_hartid; i <= last_hartid; i++) {
        if (ms->possible_cpus->cpus[i].props.node_id != socket_id) {
            return false;
        }
    }

    return true;
}

uint64_t riscv_socket_mem_offset(const MachineState *ms, int socket_id)
{
    int i;
    uint64_t mem_offset = 0;

    if (!numa_enabled(ms)) {
        return 0;
    }

    for (i = 0; i < ms->numa_state->num_nodes; i++) {
        if (i == socket_id) {
            break;
        }
        mem_offset += ms->numa_state->nodes[i].node_mem;
    }

    return (i == socket_id) ? mem_offset : 0;
}

uint64_t riscv_socket_mem_size(const MachineState *ms, int socket_id)
{
    if (!numa_enabled(ms)) {
        return (!socket_id) ? ms->ram_size : 0;
    }

    return (socket_id < ms->numa_state->num_nodes) ?
            ms->numa_state->nodes[socket_id].node_mem : 0;
}

void riscv_socket_fdt_write_id(const MachineState *ms, void *fdt,
                               const char *node_name, int socket_id)
{
    if (numa_enabled(ms)) {
        qemu_fdt_setprop_cell(fdt, node_name, "numa-node-id", socket_id);
    }
}

void riscv_socket_fdt_write_distance_matrix(const MachineState *ms, void *fdt)
{
    int i, j, idx;
    uint32_t *dist_matrix, dist_matrix_size;

    if (numa_enabled(ms) && ms->numa_state->have_numa_distance) {
        dist_matrix_size = riscv_socket_count(ms) * riscv_socket_count(ms);
        dist_matrix_size *= (3 * sizeof(uint32_t));
        dist_matrix = g_malloc0(dist_matrix_size);

        for (i = 0; i < riscv_socket_count(ms); i++) {
            for (j = 0; j < riscv_socket_count(ms); j++) {
                idx = (i * riscv_socket_count(ms) + j) * 3;
                dist_matrix[idx + 0] = cpu_to_be32(i);
                dist_matrix[idx + 1] = cpu_to_be32(j);
                dist_matrix[idx + 2] =
                    cpu_to_be32(ms->numa_state->nodes[i].distance[j]);
            }
        }

        qemu_fdt_add_subnode(fdt, "/distance-map");
        qemu_fdt_setprop_string(fdt, "/distance-map", "compatible",
                                "numa-distance-map-v1");
        qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix",
                         dist_matrix, dist_matrix_size);
        g_free(dist_matrix);
    }
}

CpuInstanceProperties
riscv_numa_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
{
    MachineClass *mc = MACHINE_GET_CLASS(ms);
    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);

    assert(cpu_index < possible_cpus->len);
    return possible_cpus->cpus[cpu_index].props;
}

int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx)
{
    int64_t nidx = 0;

    if (ms->numa_state->num_nodes) {
        nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
        if (ms->numa_state->num_nodes <= nidx) {
            nidx = ms->numa_state->num_nodes - 1;
        }
    }

    return nidx;
}

const CPUArchIdList *riscv_numa_possible_cpu_arch_ids(MachineState *ms)
{
    int n;
    unsigned int max_cpus = ms->smp.max_cpus;

    if (ms->possible_cpus) {
        assert(ms->possible_cpus->len == max_cpus);
        return ms->possible_cpus;
    }

    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
                                  sizeof(CPUArchId) * max_cpus);
    ms->possible_cpus->len = max_cpus;
    for (n = 0; n < ms->possible_cpus->len; n++) {
        ms->possible_cpus->cpus[n].type = ms->cpu_type;
        ms->possible_cpus->cpus[n].arch_id = n;
        ms->possible_cpus->cpus[n].props.has_core_id = true;
        ms->possible_cpus->cpus[n].props.core_id = n;
    }

    return ms->possible_cpus;
}
