/*
 * Intel IOMMU unit test.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Authors:
 *   Peter Xu <peterx@redhat.com>,
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or
 * later.
 */

#include "intel-iommu.h"
#include "pci-edu.h"
#include "x86/apic.h"
#include "vm.h"
#include "alloc_page.h"

#define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test")
#define VTD_TEST_IR_MSI ("IR MSI")
#define VTD_TEST_IR_IOAPIC ("IR IOAPIC")

static struct pci_edu_dev edu_dev;

static void vtd_test_dmar(void)
{
	struct pci_edu_dev *dev = &edu_dev;
	void *page = alloc_page();

	report_prefix_push("vtd_dmar");

#define DMA_TEST_WORD (0x12345678)
	/* Modify the first 4 bytes of the page */
	*(uint32_t *)page = DMA_TEST_WORD;

	/*
	 * Map the newly allocated page into IOVA address 0 (size 4K)
	 * of the device address space. Root entry and context entry
	 * will be automatically created when needed.
	 */
	vtd_map_range(dev->pci_dev.bdf, 0, virt_to_phys(page), PAGE_SIZE);

	/*
	 * DMA the first 4 bytes of the page to EDU device buffer
	 * offset 0.
	 */
	edu_dma(dev, 0, 4, 0, false);

	/*
	 * DMA the first 4 bytes of EDU device buffer into the page
	 * with offset 4 (so it'll be using 4-7 bytes).
	 */
	edu_dma(dev, 4, 4, 0, true);

	/*
	 * Check data match between 0-3 bytes and 4-7 bytes of the
	 * page.
	 */
	report(*((uint32_t *)page + 1) == DMA_TEST_WORD, VTD_TEST_DMAR_4B);

	free_page(page);

	report_prefix_pop();
}

static volatile bool edu_intr_recved;

static void edu_isr(isr_regs_t *regs)
{
	edu_intr_recved = true;
	eoi();
	edu_reg_writel(&edu_dev, EDU_REG_INTR_ACK,
			edu_reg_readl(&edu_dev, EDU_REG_INTR_STATUS));
}

static void vtd_test_ir(void)
{
#define VTD_TEST_VECTOR_IOAPIC (0xed)
#define VTD_TEST_VECTOR_MSI (0xee)
	struct pci_edu_dev *dev = &edu_dev;
	struct pci_dev *pci_dev = &dev->pci_dev;

	report_prefix_push("vtd_ir");

	irq_enable();

	/* This will enable INTx */
	pci_msi_set_enable(pci_dev, false);
	vtd_setup_ioapic_irq(pci_dev, VTD_TEST_VECTOR_IOAPIC,
			     0, TRIGGER_EDGE);
	handle_irq(VTD_TEST_VECTOR_IOAPIC, edu_isr);

	edu_intr_recved = false;
	wmb();
	/* Manually trigger INTR */
	edu_reg_writel(dev, EDU_REG_INTR_RAISE, 1);

	while (!edu_intr_recved)
		cpu_relax();

	/* Clear INTR bits */
	edu_reg_writel(dev, EDU_REG_INTR_RAISE, 0);

	/* We are good as long as we reach here */
	report(edu_intr_recved == true, VTD_TEST_IR_IOAPIC);

	/*
	 * Setup EDU PCI device MSI, using interrupt remapping. By
	 * default, EDU device is using INTx.
	 */
	if (!vtd_setup_msi(pci_dev, VTD_TEST_VECTOR_MSI, 0)) {
		printf("edu device does not support MSI, skip test\n");
		report_skip(VTD_TEST_IR_MSI);
		return;
	}

	handle_irq(VTD_TEST_VECTOR_MSI, edu_isr);

	edu_intr_recved = false;
	wmb();
	/* Manually trigger INTR */
	edu_reg_writel(dev, EDU_REG_INTR_RAISE, 1);

	while (!edu_intr_recved)
		cpu_relax();

	/* We are good as long as we reach here */
	report(edu_intr_recved == true, VTD_TEST_IR_MSI);

	report_prefix_pop();
}

int main(int argc, char *argv[])
{
	setup_vm();

	vtd_init();

	report_prefix_push("vtd_init");

	report(vtd_readl(DMAR_FSTS_REG) == 0, "fault status check");
	report(vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_QI, "QI enablement");
	report(vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_ROOT, "DMAR table setup");
	report(vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE, "IR table setup");
	report(vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR, "DMAR enablement");
	report(vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR, "IR enablement");
	report(vtd_readq(DMAR_CAP_REG) & VTD_CAP_SAGAW,
	       "DMAR support 39 bits address width");
	report(vtd_readq(DMAR_CAP_REG) & VTD_CAP_SLLPS,
	       "DMAR support huge pages");

	report_prefix_pop();

	if (!edu_init(&edu_dev)) {
		printf("Please specify \"-device edu\" to do "
		       "further IOMMU tests.\n");
		report_skip(VTD_TEST_DMAR_4B);
		report_skip(VTD_TEST_IR_IOAPIC);
		report_skip(VTD_TEST_IR_MSI);
	} else {
		printf("Found EDU device:\n");
		pci_dev_print(&edu_dev.pci_dev);
		vtd_test_dmar();
		vtd_test_ir();
	}

	return report_summary();
}
