/*
 * QEMU sPAPR IOMMU (TCE) code
 *
 * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
#include "hw.h"
#include "kvm.h"
#include "qdev.h"
#include "kvm_ppc.h"
#include "dma.h"
#include "exec-memory.h"

#include "hw/spapr.h"

#include <libfdt.h>

/* #define DEBUG_TCE */

enum sPAPRTCEAccess {
    SPAPR_TCE_FAULT = 0,
    SPAPR_TCE_RO = 1,
    SPAPR_TCE_WO = 2,
    SPAPR_TCE_RW = 3,
};

typedef struct sPAPRTCETable sPAPRTCETable;

struct sPAPRTCETable {
    DMAContext dma;
    uint32_t liobn;
    uint32_t window_size;
    sPAPRTCE *table;
    bool bypass;
    int fd;
    QLIST_ENTRY(sPAPRTCETable) list;
};


QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;

static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
{
    sPAPRTCETable *tcet;

    QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
        if (tcet->liobn == liobn) {
            return tcet;
        }
    }

    return NULL;
}

static int spapr_tce_translate(DMAContext *dma,
                               dma_addr_t addr,
                               hwaddr *paddr,
                               hwaddr *len,
                               DMADirection dir)
{
    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
    uint64_t tce;

#ifdef DEBUG_TCE
    fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
            DMA_ADDR_FMT "\n", tcet->liobn, addr);
#endif

    if (tcet->bypass) {
        *paddr = addr;
        *len = (hwaddr)-1;
        return 0;
    }

    /* Check if we are in bound */
    if (addr >= tcet->window_size) {
#ifdef DEBUG_TCE
        fprintf(stderr, "spapr_tce_translate out of bounds\n");
#endif
        return -EFAULT;
    }

    tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;

    /* Check TCE */
    if (!(tce & access)) {
        return -EPERM;
    }

    /* How much til end of page ? */
    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;

    /* Translate */
    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
        (addr & SPAPR_TCE_PAGE_MASK);

#ifdef DEBUG_TCE
    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
            TARGET_FMT_plx "\n", *paddr, *len);
#endif

    return 0;
}

DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
{
    sPAPRTCETable *tcet;

    if (spapr_tce_find_by_liobn(liobn)) {
        fprintf(stderr, "Attempted to create TCE table with duplicate"
                " LIOBN 0x%x\n", liobn);
        return NULL;
    }

    if (!window_size) {
        return NULL;
    }

    tcet = g_malloc0(sizeof(*tcet));
    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);

    tcet->liobn = liobn;
    tcet->window_size = window_size;

    if (kvm_enabled()) {
        tcet->table = kvmppc_create_spapr_tce(liobn,
                                              window_size,
                                              &tcet->fd);
    }

    if (!tcet->table) {
        size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
            * sizeof(sPAPRTCE);
        tcet->table = g_malloc0(table_size);
    }

#ifdef DEBUG_TCE
    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
#endif

    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);

    return &tcet->dma;
}

void spapr_tce_free(DMAContext *dma)
{

    if (dma) {
        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);

        QLIST_REMOVE(tcet, list);

        if (!kvm_enabled() ||
            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
                                     tcet->window_size) != 0)) {
            g_free(tcet->table);
        }

        g_free(tcet);
    }
}

void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
{
    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);

    tcet->bypass = bypass;
}

void spapr_tce_reset(DMAContext *dma)
{
    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
    size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
        * sizeof(sPAPRTCE);

    tcet->bypass = false;
    memset(tcet->table, 0, table_size);
}

static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
                                target_ulong tce)
{
    sPAPRTCE *tcep;

    if (ioba >= tcet->window_size) {
        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
                      TARGET_FMT_lx "\n", ioba);
        return H_PARAMETER;
    }

    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
    tcep->tce = tce;

    return H_SUCCESS;
}

static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                              target_ulong opcode, target_ulong *args)
{
    target_ulong liobn = args[0];
    target_ulong ioba = args[1];
    target_ulong tce = args[2];
    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);

    if (liobn & 0xFFFFFFFF00000000ULL) {
        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
                      TARGET_FMT_lx "\n", liobn);
        return H_PARAMETER;
    }

    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);

    if (tcet) {
        return put_tce_emu(tcet, ioba, tce);
    }
#ifdef DEBUG_TCE
    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
            __func__, liobn, /*dev->qdev.id, */ioba, tce);
#endif

    return H_PARAMETER;
}

void spapr_iommu_init(void)
{
    QLIST_INIT(&spapr_tce_tables);

    /* hcall-tce */
    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
}

int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                 uint32_t liobn, uint64_t window, uint32_t size)
{
    uint32_t dma_prop[5];
    int ret;

    dma_prop[0] = cpu_to_be32(liobn);
    dma_prop[1] = cpu_to_be32(window >> 32);
    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
    dma_prop[3] = 0; /* window size is 32 bits */
    dma_prop[4] = cpu_to_be32(size);

    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
    if (ret < 0) {
        return ret;
    }

    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
    if (ret < 0) {
        return ret;
    }

    ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop));
    if (ret < 0) {
        return ret;
    }

    return 0;
}

int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
                      DMAContext *iommu)
{
    if (!iommu) {
        return 0;
    }

    if (iommu->translate == spapr_tce_translate) {
        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
        return spapr_dma_dt(fdt, node_off, propname,
                tcet->liobn, 0, tcet->window_size);
    }

    return -1;
}
