/*
 * Copyright (c) 2020 Nutanix Inc. All rights reserved.
 *
 * Authors: Thanos Makatos <thanos@nutanix.com>
 *          Swapnil Ingle <swapnil.ingle@nutanix.com>
 *          Felipe Franciosi <felipe@nutanix.com>
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Nutanix nor the names of its contributors may be
 *        used to endorse or promote products derived from this software without
 *        specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 *  DAMAGE.
 *
 */

#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/eventfd.h>

#include "irq.h"

#define LM2VFIO_IRQT(type) (type - 1)

static const char *
vfio_irq_idx_to_str(int index)
{
    switch (index) {
    case VFIO_PCI_INTX_IRQ_INDEX: return "INTx";
    case VFIO_PCI_MSI_IRQ_INDEX: return "MSI";
    case VFIO_PCI_MSIX_IRQ_INDEX: return "MSI-X";
    case VFIO_PCI_ERR_IRQ_INDEX: return "ERR";
    case VFIO_PCI_REQ_IRQ_INDEX: return "REQ";
    default:
        abort();
    }
}

int
handle_device_get_irq_info(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
{
    struct vfio_irq_info *in_info;
    struct vfio_irq_info *out_info;

    assert(vfu_ctx != NULL);
    assert(msg != NULL);

    in_info = msg->in.iov.iov_base;

    if (msg->in.iov.iov_len < sizeof(*in_info) || in_info->argsz < sizeof(*out_info)) {
        return ERROR_INT(EINVAL);
    }

    if (in_info->index >= VFU_DEV_NUM_IRQS) {
        vfu_log(vfu_ctx, LOG_DEBUG, "bad irq_info index %d\n", in_info->index);
        return ERROR_INT(EINVAL);
    }

    msg->out.iov.iov_len = sizeof (*out_info);
    msg->out.iov.iov_base = calloc(1, sizeof(*out_info));

    if (msg->out.iov.iov_base == NULL) {
        return -1;
    }

    out_info = msg->out.iov.iov_base;
    out_info->argsz = sizeof(*out_info);
    out_info->flags = VFIO_IRQ_INFO_EVENTFD;
    out_info->index = in_info->index;
    out_info->count = vfu_ctx->irq_count[in_info->index];

    return 0;
}

static void
irqs_disable(vfu_ctx_t *vfu_ctx, uint32_t index, uint32_t start, uint32_t count)
{
    size_t i;
    int *efds;

    assert(vfu_ctx != NULL);
    assert(index < VFU_DEV_NUM_IRQS);
    assert(start + count <= vfu_ctx->irq_count[index]);

    if (count == 0) {
        count = vfu_ctx->irq_count[index];
    }

    vfu_log(vfu_ctx, LOG_DEBUG, "disabling IRQ type %s range [%u, %u)",
            vfio_irq_idx_to_str(index), start, start + count);

    switch (index) {
    case VFIO_PCI_INTX_IRQ_INDEX:
    case VFIO_PCI_MSI_IRQ_INDEX:
    case VFIO_PCI_MSIX_IRQ_INDEX:
        efds = vfu_ctx->irqs->efds;
        break;
    case VFIO_PCI_ERR_IRQ_INDEX:
        efds = &vfu_ctx->irqs->err_efd;
        break;
    case VFIO_PCI_REQ_IRQ_INDEX:
        efds = &vfu_ctx->irqs->req_efd;
        break;
    }

    for (i = start; i < count; i++) {
        if (efds[i] >= 0) {
            if (close(efds[i]) == -1) {
                vfu_log(vfu_ctx, LOG_DEBUG, "failed to close IRQ fd %d: %m",
                        efds[i]);
            }

            efds[i] = -1;
        }
    }
}

void
irqs_reset(vfu_ctx_t *vfu_ctx)
{
    int *efds = vfu_ctx->irqs->efds;
    size_t i;

    irqs_disable(vfu_ctx, VFIO_PCI_REQ_IRQ_INDEX, 0, 0);
    irqs_disable(vfu_ctx, VFIO_PCI_ERR_IRQ_INDEX, 0, 0);

    for (i = 0; i < vfu_ctx->irqs->max_ivs; i++) {
        if (efds[i] >= 0) {
            if (close(efds[i]) == -1) {
                vfu_log(vfu_ctx, LOG_DEBUG, "failed to close IRQ fd %d: %m",
                        efds[i]);
            }

            efds[i] = -1;
        }
    }
}

static void
irqs_set_state(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set)
{
    vfu_dev_irq_state_cb_t *cb = NULL;
    uint32_t irq_action;
    bool mask = false;

    assert(irq_set->index < VFU_DEV_NUM_IRQS);
    cb = vfu_ctx->irq_state_cbs[irq_set->index];
    if (cb == NULL) {
        return;
    }

    assert((irq_set->start + irq_set->count) <=
            vfu_ctx->irq_count[irq_set->index]);

    irq_action = irq_set->flags & VFIO_IRQ_SET_ACTION_TYPE_MASK;

    assert((irq_action & VFIO_IRQ_SET_ACTION_MASK) ||
           (irq_action & VFIO_IRQ_SET_ACTION_UNMASK));

    mask = (irq_action & VFIO_IRQ_SET_ACTION_MASK) ? true : false;

    cb(vfu_ctx, irq_set->start, irq_set->count, mask);
}

static int *
irqs_get_efd(vfu_ctx_t *vfu_ctx, int index, int fd_idx)
{
    switch (index) {
    case VFIO_PCI_ERR_IRQ_INDEX:
        return &vfu_ctx->irqs->err_efd;
    case VFIO_PCI_REQ_IRQ_INDEX:
        return &vfu_ctx->irqs->req_efd;
    default:
        return &vfu_ctx->irqs->efds[fd_idx];
    }
}

static int
irqs_set_data_none(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set)
{
    int *efd;
    uint32_t i;
    long ret;
    eventfd_t val;

    for (i = irq_set->start; i < (irq_set->start + irq_set->count); i++) {
        efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
        if (*efd >= 0) {
            val = 1;
            ret = eventfd_write(*efd, val);
            if (ret == -1) {
                vfu_log(vfu_ctx, LOG_DEBUG,
                        "IRQ: failed to set data to none: %m");
                return -1;
            }
        }
    }

    return 0;
}

static int
irqs_set_data_bool(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set, void *data)
{
    uint8_t *d8;
    int *efd;
    uint32_t i;
    long ret;
    eventfd_t val;

    assert(data != NULL);

    for (i = irq_set->start, d8 = data; i < (irq_set->start + irq_set->count);
         i++, d8++) {
        efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
        if (*efd >= 0 && *d8 == 1) {
            val = 1;
            ret = eventfd_write(*efd, val);
            if (ret == -1) {
                vfu_log(vfu_ctx, LOG_DEBUG,
                        "IRQ: failed to set data to bool: %m");
                return -1;
            }
        }
    }

    return 0;
}

static int
irqs_set_data_eventfd(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set,
                      int *data)
{
    int *efd;
    uint32_t i;
    size_t j;

    assert(data != NULL);
    for (i = irq_set->start, j = 0; i < (irq_set->start + irq_set->count);
         i++, j++) {
        efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
        if (*efd >= 0) {
            if (close(*efd) == -1) {
                vfu_log(vfu_ctx, LOG_DEBUG, "failed to close IRQ fd %d: %m", *efd);
            }
            *efd = -1;
        }
        assert(data[j] >= 0);
        /*
         * We've already checked in handle_device_set_irqs that
         * nr_fds == irq_set->count.
         */
        *efd = consume_fd(data, irq_set->count, j);
        switch (irq_set->index) {
        case VFIO_PCI_ERR_IRQ_INDEX:
            vfu_log(vfu_ctx, LOG_DEBUG, "err fd=%d", *efd);
            break;
        case VFIO_PCI_REQ_IRQ_INDEX:
            vfu_log(vfu_ctx, LOG_DEBUG, "req fd=%d", *efd);
            break;
        default:
            vfu_log(vfu_ctx, LOG_DEBUG, "event fd[%d]=%d", i, *efd);
            break;
        }
    }

    return 0;
}

static int
device_set_irqs_validate(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
{
    struct vfio_irq_set *irq_set = msg->in.iov.iov_base;
    uint32_t a_type, d_type;
    int line;

    assert(vfu_ctx != NULL);
    assert(irq_set != NULL);

    if (msg->in.iov.iov_len < sizeof(*irq_set) || irq_set->argsz < sizeof(*irq_set)) {
        vfu_log(vfu_ctx, LOG_ERR, "bad size %zu", msg->in.iov.iov_len);
        return ERROR_INT(EINVAL);
    }

    // Separate action and data types from flags.
    a_type = (irq_set->flags & VFIO_IRQ_SET_ACTION_TYPE_MASK);
    d_type = (irq_set->flags & VFIO_IRQ_SET_DATA_TYPE_MASK);

    // bools provided must match count
    if (d_type == VFIO_IRQ_SET_DATA_BOOL &&
        (msg->in.iov.iov_len - sizeof(*irq_set) != sizeof(uint8_t) * irq_set->count)) {
        line = __LINE__;
        goto invalid;
    }

    // Ensure index is within bounds.
    if (irq_set->index >= VFU_DEV_NUM_IRQS) {
        line = __LINE__;
        goto invalid;
    }

    // Only one of MASK/UNMASK/TRIGGER is valid.
    if ((a_type != VFIO_IRQ_SET_ACTION_MASK) &&
        (a_type != VFIO_IRQ_SET_ACTION_UNMASK) &&
        (a_type != VFIO_IRQ_SET_ACTION_TRIGGER)) {
        line = __LINE__;
        goto invalid;
    }
    // Only one of NONE/BOOL/EVENTFD is valid.
    if ((d_type != VFIO_IRQ_SET_DATA_NONE) &&
        (d_type != VFIO_IRQ_SET_DATA_BOOL) &&
        (d_type != VFIO_IRQ_SET_DATA_EVENTFD)) {
        line = __LINE__;
        goto invalid;
    }
    // Ensure irq_set's start and count are within bounds.
    if ((irq_set->start >= vfu_ctx->irq_count[irq_set->index]) ||
        (irq_set->start + irq_set->count > vfu_ctx->irq_count[irq_set->index])) {
        line = __LINE__;
        goto invalid;
    }
    // Only TRIGGER is valid for ERR/REQ.
    if (((irq_set->index == VFIO_PCI_ERR_IRQ_INDEX) ||
         (irq_set->index == VFIO_PCI_REQ_IRQ_INDEX)) &&
        (a_type != VFIO_IRQ_SET_ACTION_TRIGGER)) {
        line = __LINE__;
        goto invalid;
    }
    // count must be 0 or 1 for ERR/REQ
    if (((irq_set->index == VFIO_PCI_ERR_IRQ_INDEX) ||
         (irq_set->index == VFIO_PCI_REQ_IRQ_INDEX)) &&
        (irq_set->count > 1)) {
        line = __LINE__;
        goto invalid;
    }
    // if count == 0, start must be 0 too
    if ((irq_set->count == 0) && (irq_set->start != 0)) {
        line = __LINE__;
        goto invalid;
    }
    // count == 0 is only valid with ACTION_TRIGGER and DATA_NONE.
    if ((irq_set->count == 0) && ((a_type != VFIO_IRQ_SET_ACTION_TRIGGER) ||
                                  (d_type != VFIO_IRQ_SET_DATA_NONE))) {
        line = __LINE__;
        goto invalid;
    }
    // If fd's are provided, ensure it's only for VFIO_IRQ_SET_DATA_EVENTFD
    if (msg->in.nr_fds != 0 && d_type != VFIO_IRQ_SET_DATA_EVENTFD) {
        line = __LINE__;
        goto invalid;
    }
    // If fd's are provided, ensure they match ->count
    if (msg->in.nr_fds != 0 && msg->in.nr_fds != irq_set->count) {
        line = __LINE__;
        goto invalid;
    }

    return 0;

invalid:
    vfu_log(vfu_ctx, LOG_DEBUG, "invalid SET_IRQS (%d): action=%u data_type=%u "
            "index=%u start=%u count=%u nr_fds=%zu", line, a_type, d_type,
            irq_set->index, irq_set->start, irq_set->count, msg->in.nr_fds);
    return ERROR_INT(EINVAL);
}

int
handle_device_set_irqs(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
{
    struct vfio_irq_set *irq_set = msg->in.iov.iov_base;
    uint32_t data_type;
    int ret;

    assert(vfu_ctx != NULL);
    assert(msg != NULL);

    ret = device_set_irqs_validate(vfu_ctx, msg);
    if (ret != 0) {
        return ret;
    }

    switch (irq_set->flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
    case VFIO_IRQ_SET_ACTION_MASK:
    case VFIO_IRQ_SET_ACTION_UNMASK:
        irqs_set_state(vfu_ctx, irq_set);
        return 0;
    case VFIO_IRQ_SET_ACTION_TRIGGER:
        break;
    }

    data_type = irq_set->flags & VFIO_IRQ_SET_DATA_TYPE_MASK;

    if ((data_type == VFIO_IRQ_SET_DATA_NONE && irq_set->count == 0) ||
        (data_type == VFIO_IRQ_SET_DATA_EVENTFD && msg->in.nr_fds == 0)) {
        irqs_disable(vfu_ctx, irq_set->index, irq_set->start, irq_set->count);
        return 0;
    }

    vfu_log(vfu_ctx, LOG_DEBUG, "setting IRQ %s flags=%#x range [%u, %u)",
            vfio_irq_idx_to_str(irq_set->index), irq_set->flags,
            irq_set->start, irq_set->start + irq_set->count);

    switch (data_type) {
    case VFIO_IRQ_SET_DATA_NONE:
        return irqs_set_data_none(vfu_ctx, irq_set);
    case VFIO_IRQ_SET_DATA_EVENTFD:
        return irqs_set_data_eventfd(vfu_ctx, irq_set, msg->in.fds);
    case VFIO_IRQ_SET_DATA_BOOL:
        return irqs_set_data_bool(vfu_ctx, irq_set, irq_set + 1);
        break;
    default:
        // we already checked this
        abort();
    }
}

static bool
validate_irq_subindex(vfu_ctx_t *vfu_ctx, uint32_t subindex)
{
    if ((subindex >= vfu_ctx->irqs->max_ivs)) {
        vfu_log(vfu_ctx, LOG_ERR, "bad IRQ %d, max=%d", subindex,
               vfu_ctx->irqs->max_ivs);
        return false;
    }

    return true;
}

EXPORT int
vfu_irq_trigger(vfu_ctx_t *vfu_ctx, uint32_t subindex)
{
    eventfd_t val = 1;

    assert(vfu_ctx != NULL);

    if (!validate_irq_subindex(vfu_ctx, subindex)) {
        return ERROR_INT(EINVAL);
    }

    if (vfu_ctx->irqs->efds[subindex] == -1) {
        vfu_log(vfu_ctx, LOG_ERR, "no fd for interrupt %d", subindex);
        return ERROR_INT(ENOENT);
    }

    return eventfd_write(vfu_ctx->irqs->efds[subindex], val);
}

/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
