/*
 * QEMU emulation of common X86 IOMMU
 *
 * Copyright (C) 2016 Peter Xu, Red Hat <peterx@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that 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 "hw/sysbus.h"
#include "hw/i386/x86-iommu.h"
#include "hw/qdev-properties.h"
#include "hw/i386/pc.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "trace.h"
#include "sysemu/kvm.h"

void x86_iommu_iec_register_notifier(X86IOMMUState *iommu,
                                     iec_notify_fn fn, void *data)
{
    IEC_Notifier *notifier = g_new0(IEC_Notifier, 1);

    notifier->iec_notify = fn;
    notifier->private = data;

    QLIST_INSERT_HEAD(&iommu->iec_notifiers, notifier, list);
}

void x86_iommu_iec_notify_all(X86IOMMUState *iommu, bool global,
                              uint32_t index, uint32_t mask)
{
    IEC_Notifier *notifier;

    trace_x86_iommu_iec_notify(global, index, mask);

    QLIST_FOREACH(notifier, &iommu->iec_notifiers, list) {
        if (notifier->iec_notify) {
            notifier->iec_notify(notifier->private, global,
                                 index, mask);
        }
    }
}

/* Generate one MSI message from VTDIrq info */
void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *msg_out)
{
    X86IOMMU_MSIMessage msg = {};

    /* Generate address bits */
    msg.dest_mode = irq->dest_mode;
    msg.redir_hint = irq->redir_hint;
    msg.dest = irq->dest;
    msg.__addr_hi = irq->dest & 0xffffff00;
    msg.__addr_head = 0xfee;
    /* Keep this from original MSI address bits */
    msg.__not_used = irq->msi_addr_last_bits;

    /* Generate data bits */
    msg.vector = irq->vector;
    msg.delivery_mode = irq->delivery_mode;
    msg.level = 1;
    msg.trigger_mode = irq->trigger_mode;

    msg_out->address = msg.msi_addr;
    msg_out->data = msg.msi_data;
}

X86IOMMUState *x86_iommu_get_default(void)
{
    MachineState *ms = MACHINE(qdev_get_machine());
    PCMachineState *pcms =
        PC_MACHINE(object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE));

    if (pcms &&
        object_dynamic_cast(OBJECT(pcms->iommu), TYPE_X86_IOMMU_DEVICE)) {
        return X86_IOMMU_DEVICE(pcms->iommu);
    }
    return NULL;
}

static void x86_iommu_realize(DeviceState *dev, Error **errp)
{
    X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev);
    X86IOMMUClass *x86_class = X86_IOMMU_DEVICE_GET_CLASS(dev);
    MachineState *ms = MACHINE(qdev_get_machine());
    MachineClass *mc = MACHINE_GET_CLASS(ms);
    PCMachineState *pcms =
        PC_MACHINE(object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE));
    QLIST_INIT(&x86_iommu->iec_notifiers);
    bool irq_all_kernel = kvm_irqchip_in_kernel() && !kvm_irqchip_is_split();

    if (!pcms || !pcms->bus) {
        error_setg(errp, "Machine-type '%s' not supported by IOMMU",
                   mc->name);
        return;
    }

    /* If the user didn't specify IR, choose a default value for it */
    if (x86_iommu->intr_supported == ON_OFF_AUTO_AUTO) {
        x86_iommu->intr_supported = irq_all_kernel ?
            ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
    }

    /* Both Intel and AMD IOMMU IR only support "kernel-irqchip={off|split}" */
    if (x86_iommu_ir_supported(x86_iommu) && irq_all_kernel) {
        error_setg(errp, "Interrupt Remapping cannot work with "
                         "kernel-irqchip=on, please use 'split|off'.");
        return;
    }

    if (x86_class->realize) {
        x86_class->realize(dev, errp);
    }
}

static Property x86_iommu_properties[] = {
    DEFINE_PROP_ON_OFF_AUTO("intremap", X86IOMMUState,
                            intr_supported, ON_OFF_AUTO_AUTO),
    DEFINE_PROP_BOOL("device-iotlb", X86IOMMUState, dt_supported, false),
    DEFINE_PROP_BOOL("pt", X86IOMMUState, pt_supported, true),
    DEFINE_PROP_END_OF_LIST(),
};

static void x86_iommu_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    dc->realize = x86_iommu_realize;
    device_class_set_props(dc, x86_iommu_properties);
}

bool x86_iommu_ir_supported(X86IOMMUState *s)
{
    return s->intr_supported == ON_OFF_AUTO_ON;
}

static const TypeInfo x86_iommu_info = {
    .name          = TYPE_X86_IOMMU_DEVICE,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(X86IOMMUState),
    .class_init    = x86_iommu_class_init,
    .class_size    = sizeof(X86IOMMUClass),
    .abstract      = true,
};

static void x86_iommu_register_types(void)
{
    type_register_static(&x86_iommu_info);
}

type_init(x86_iommu_register_types)
