/*
 * 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++) {
        close_safely(&efds[i]);
    }
}

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++) {
        close_safely(&efds[i]);
    }
}

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);
        close_safely(efd);
        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 is within bounds.
    if (irq_set->start >= vfu_ctx->irq_count[irq_set->index]) {
        line = __LINE__;
        goto invalid;
    }

    // Ensure irq_set's start+count is within bounds.
    if (satadd_u32(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: */
