/*
 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
 *
 * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics, in-kernel emulation
 *
 * Copyright (c) 2013 David Gibson, IBM Corporation.
 *
 * 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 "qemu-common.h"
#include "cpu.h"
#include "trace.h"
#include "sysemu/kvm.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/xics.h"
#include "hw/ppc/xics_spapr.h"
#include "kvm_ppc.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"

#include <sys/ioctl.h>

static int kernel_xics_fd = -1;

typedef struct KVMEnabledICP {
    unsigned long vcpu_id;
    QLIST_ENTRY(KVMEnabledICP) node;
} KVMEnabledICP;

static QLIST_HEAD(, KVMEnabledICP)
    kvm_enabled_icps = QLIST_HEAD_INITIALIZER(&kvm_enabled_icps);

static void kvm_disable_icps(void)
{
    KVMEnabledICP *enabled_icp, *next;

    QLIST_FOREACH_SAFE(enabled_icp, &kvm_enabled_icps, node, next) {
        QLIST_REMOVE(enabled_icp, node);
        g_free(enabled_icp);
    }
}

/*
 * ICP-KVM
 */
void icp_get_kvm_state(ICPState *icp)
{
    uint64_t state;
    int ret;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return;
    }

    /* ICP for this CPU thread is not in use, exiting */
    if (!icp->cs) {
        return;
    }

    ret = kvm_get_one_reg(icp->cs, KVM_REG_PPC_ICP_STATE, &state);
    if (ret != 0) {
        error_report("Unable to retrieve KVM interrupt controller state"
                " for CPU %ld: %s", kvm_arch_vcpu_id(icp->cs), strerror(errno));
        exit(1);
    }

    icp->xirr = state >> KVM_REG_PPC_ICP_XISR_SHIFT;
    icp->mfrr = (state >> KVM_REG_PPC_ICP_MFRR_SHIFT)
        & KVM_REG_PPC_ICP_MFRR_MASK;
    icp->pending_priority = (state >> KVM_REG_PPC_ICP_PPRI_SHIFT)
        & KVM_REG_PPC_ICP_PPRI_MASK;
}

static void do_icp_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{
    icp_get_kvm_state(arg.host_ptr);
}

void icp_synchronize_state(ICPState *icp)
{
    if (icp->cs) {
        run_on_cpu(icp->cs, do_icp_synchronize_state, RUN_ON_CPU_HOST_PTR(icp));
    }
}

int icp_set_kvm_state(ICPState *icp, Error **errp)
{
    uint64_t state;
    int ret;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return 0;
    }

    /* ICP for this CPU thread is not in use, exiting */
    if (!icp->cs) {
        return 0;
    }

    state = ((uint64_t)icp->xirr << KVM_REG_PPC_ICP_XISR_SHIFT)
        | ((uint64_t)icp->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT)
        | ((uint64_t)icp->pending_priority << KVM_REG_PPC_ICP_PPRI_SHIFT);

    ret = kvm_set_one_reg(icp->cs, KVM_REG_PPC_ICP_STATE, &state);
    if (ret < 0) {
        error_setg_errno(errp, -ret,
                         "Unable to restore KVM interrupt controller state (0x%"
                         PRIx64 ") for CPU %ld", state,
                         kvm_arch_vcpu_id(icp->cs));
        return ret;
    }

    return 0;
}

void icp_kvm_realize(DeviceState *dev, Error **errp)
{
    ICPState *icp = ICP(dev);
    CPUState *cs;
    KVMEnabledICP *enabled_icp;
    unsigned long vcpu_id;
    int ret;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return;
    }

    cs = icp->cs;
    vcpu_id = kvm_arch_vcpu_id(cs);

    /*
     * If we are reusing a parked vCPU fd corresponding to the CPU
     * which was hot-removed earlier we don't have to renable
     * KVM_CAP_IRQ_XICS capability again.
     */
    QLIST_FOREACH(enabled_icp, &kvm_enabled_icps, node) {
        if (enabled_icp->vcpu_id == vcpu_id) {
            return;
        }
    }

    ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd, vcpu_id);
    if (ret < 0) {
        Error *local_err = NULL;

        error_setg(&local_err, "Unable to connect CPU%ld to kernel XICS: %s",
                   vcpu_id, strerror(errno));
        if (errno == ENOSPC) {
            error_append_hint(&local_err, "Try -smp maxcpus=N with N < %u\n",
                              MACHINE(qdev_get_machine())->smp.max_cpus);
        }
        error_propagate(errp, local_err);
        return;
    }
    enabled_icp = g_malloc(sizeof(*enabled_icp));
    enabled_icp->vcpu_id = vcpu_id;
    QLIST_INSERT_HEAD(&kvm_enabled_icps, enabled_icp, node);
}

/*
 * ICS-KVM
 */
void ics_get_kvm_state(ICSState *ics)
{
    uint64_t state;
    int i;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return;
    }

    for (i = 0; i < ics->nr_irqs; i++) {
        ICSIRQState *irq = &ics->irqs[i];

        if (ics_irq_free(ics, i)) {
            continue;
        }

        kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
                          i + ics->offset, &state, false, &error_fatal);

        irq->server = state & KVM_XICS_DESTINATION_MASK;
        irq->saved_priority = (state >> KVM_XICS_PRIORITY_SHIFT)
            & KVM_XICS_PRIORITY_MASK;
        /*
         * To be consistent with the software emulation in xics.c, we
         * split out the masked state + priority that we get from the
         * kernel into 'current priority' (0xff if masked) and
         * 'saved priority' (if masked, this is the priority the
         * interrupt had before it was masked).  Masking and unmasking
         * are done with the ibm,int-off and ibm,int-on RTAS calls.
         */
        if (state & KVM_XICS_MASKED) {
            irq->priority = 0xff;
        } else {
            irq->priority = irq->saved_priority;
        }

        irq->status = 0;
        if (state & KVM_XICS_PENDING) {
            if (state & KVM_XICS_LEVEL_SENSITIVE) {
                irq->status |= XICS_STATUS_ASSERTED;
            } else {
                /*
                 * A pending edge-triggered interrupt (or MSI)
                 * must have been rejected previously when we
                 * first detected it and tried to deliver it,
                 * so mark it as pending and previously rejected
                 * for consistency with how xics.c works.
                 */
                irq->status |= XICS_STATUS_MASKED_PENDING
                    | XICS_STATUS_REJECTED;
            }
        }
        if (state & KVM_XICS_PRESENTED) {
                irq->status |= XICS_STATUS_PRESENTED;
        }
        if (state & KVM_XICS_QUEUED) {
                irq->status |= XICS_STATUS_QUEUED;
        }
    }
}

void ics_synchronize_state(ICSState *ics)
{
    ics_get_kvm_state(ics);
}

int ics_set_kvm_state_one(ICSState *ics, int srcno, Error **errp)
{
    uint64_t state;
    ICSIRQState *irq = &ics->irqs[srcno];
    int ret;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return 0;
    }

    state = irq->server;
    state |= (uint64_t)(irq->saved_priority & KVM_XICS_PRIORITY_MASK)
        << KVM_XICS_PRIORITY_SHIFT;
    if (irq->priority != irq->saved_priority) {
        assert(irq->priority == 0xff);
    }

    if (irq->priority == 0xff) {
        state |= KVM_XICS_MASKED;
    }

    if (irq->flags & XICS_FLAGS_IRQ_LSI) {
        state |= KVM_XICS_LEVEL_SENSITIVE;
        if (irq->status & XICS_STATUS_ASSERTED) {
            state |= KVM_XICS_PENDING;
        }
    } else {
        if (irq->status & XICS_STATUS_MASKED_PENDING) {
            state |= KVM_XICS_PENDING;
        }
    }
    if (irq->status & XICS_STATUS_PRESENTED) {
        state |= KVM_XICS_PRESENTED;
    }
    if (irq->status & XICS_STATUS_QUEUED) {
        state |= KVM_XICS_QUEUED;
    }

    ret = kvm_device_access(kernel_xics_fd, KVM_DEV_XICS_GRP_SOURCES,
                            srcno + ics->offset, &state, true, errp);
    if (ret < 0) {
        return ret;
    }

    return 0;
}

int ics_set_kvm_state(ICSState *ics, Error **errp)
{
    int i;

    /* The KVM XICS device is not in use */
    if (kernel_xics_fd == -1) {
        return 0;
    }

    for (i = 0; i < ics->nr_irqs; i++) {
        Error *local_err = NULL;
        int ret;

        if (ics_irq_free(ics, i)) {
            continue;
        }

        ret = ics_set_kvm_state_one(ics, i, &local_err);
        if (ret < 0) {
            error_propagate(errp, local_err);
            return ret;
        }
    }

    return 0;
}

void ics_kvm_set_irq(ICSState *ics, int srcno, int val)
{
    struct kvm_irq_level args;
    int rc;

    /* The KVM XICS device should be in use */
    assert(kernel_xics_fd != -1);

    args.irq = srcno + ics->offset;
    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MSI) {
        if (!val) {
            return;
        }
        args.level = KVM_INTERRUPT_SET;
    } else {
        args.level = val ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
    }
    rc = kvm_vm_ioctl(kvm_state, KVM_IRQ_LINE, &args);
    if (rc < 0) {
        perror("kvm_irq_line");
    }
}

int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers,
                     Error **errp)
{
    ICSState *ics = ICS_SPAPR(intc);
    int rc;
    CPUState *cs;
    Error *local_err = NULL;

    /*
     * The KVM XICS device already in use. This is the case when
     * rebooting under the XICS-only interrupt mode.
     */
    if (kernel_xics_fd != -1) {
        return 0;
    }

    if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) {
        error_setg(errp,
                   "KVM and IRQ_XICS capability must be present for in-kernel XICS");
        return -1;
    }

    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_SET_XIVE, "ibm,set-xive");
    if (rc < 0) {
        error_setg_errno(&local_err, -rc,
                         "kvmppc_define_rtas_kernel_token: ibm,set-xive");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_GET_XIVE, "ibm,get-xive");
    if (rc < 0) {
        error_setg_errno(&local_err, -rc,
                         "kvmppc_define_rtas_kernel_token: ibm,get-xive");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_ON, "ibm,int-on");
    if (rc < 0) {
        error_setg_errno(&local_err, -rc,
                         "kvmppc_define_rtas_kernel_token: ibm,int-on");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_OFF, "ibm,int-off");
    if (rc < 0) {
        error_setg_errno(&local_err, -rc,
                         "kvmppc_define_rtas_kernel_token: ibm,int-off");
        goto fail;
    }

    /* Create the KVM XICS device */
    rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
    if (rc < 0) {
        error_setg_errno(&local_err, -rc, "Error on KVM_CREATE_DEVICE for XICS");
        goto fail;
    }

    /* Tell KVM about the # of VCPUs we may have (POWER9 and newer only) */
    if (kvm_device_check_attr(rc, KVM_DEV_XICS_GRP_CTRL,
                              KVM_DEV_XICS_NR_SERVERS)) {
        if (kvm_device_access(rc, KVM_DEV_XICS_GRP_CTRL,
                              KVM_DEV_XICS_NR_SERVERS, &nr_servers, true,
                              &local_err)) {
            goto fail;
        }
    }

    kernel_xics_fd = rc;
    kvm_kernel_irqchip = true;
    kvm_msi_via_irqfd_allowed = true;
    kvm_gsi_direct_mapping = true;

    /* Create the presenters */
    CPU_FOREACH(cs) {
        PowerPCCPU *cpu = POWERPC_CPU(cs);

        icp_kvm_realize(DEVICE(spapr_cpu_state(cpu)->icp), &local_err);
        if (local_err) {
            goto fail;
        }
    }

    /* Update the KVM sources */
    ics_set_kvm_state(ics, &local_err);
    if (local_err) {
        goto fail;
    }

    /* Connect the presenters to the initial VCPUs of the machine */
    CPU_FOREACH(cs) {
        PowerPCCPU *cpu = POWERPC_CPU(cs);
        icp_set_kvm_state(spapr_cpu_state(cpu)->icp, &local_err);
        if (local_err) {
            goto fail;
        }
    }

    return 0;

fail:
    error_propagate(errp, local_err);
    xics_kvm_disconnect(intc);
    return -1;
}

void xics_kvm_disconnect(SpaprInterruptController *intc)
{
    /*
     * Only on P9 using the XICS-on XIVE KVM device:
     *
     * When the KVM device fd is closed, the device is destroyed and
     * removed from the list of devices of the VM. The VCPU presenters
     * are also detached from the device.
     */
    if (kernel_xics_fd != -1) {
        close(kernel_xics_fd);
        kernel_xics_fd = -1;
    }

    kvmppc_define_rtas_kernel_token(0, "ibm,set-xive");
    kvmppc_define_rtas_kernel_token(0, "ibm,get-xive");
    kvmppc_define_rtas_kernel_token(0, "ibm,int-on");
    kvmppc_define_rtas_kernel_token(0, "ibm,int-off");

    kvm_kernel_irqchip = false;
    kvm_msi_via_irqfd_allowed = false;
    kvm_gsi_direct_mapping = false;

    /* Clear the presenter from the VCPUs */
    kvm_disable_icps();
}

/*
 * This is a heuristic to detect older KVMs on POWER9 hosts that don't
 * support destruction of a KVM XICS device while the VM is running.
 * Required to start a spapr machine with ic-mode=dual,kernel-irqchip=on.
 */
bool xics_kvm_has_broken_disconnect(SpaprMachineState *spapr)
{
    int rc;

    rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
    if (rc < 0) {
        /*
         * The error is ignored on purpose. The KVM XICS setup code
         * will catch it again anyway. The goal here is to see if
         * close() actually destroys the device or not.
         */
        return false;
    }

    close(rc);

    rc = kvm_create_device(kvm_state, KVM_DEV_TYPE_XICS, false);
    if (rc >= 0) {
        close(rc);
        return false;
    }

    return errno == EEXIST;
}
