HAS_DEVICE_TREE := y
HAS_VIDEO := y
HAS_ARM_HDLCD := y
+HAS_PASSTHROUGH := y
CFLAGS += -I$(BASEDIR)/include
if ( is_hardware_domain(d) && (rc = domain_vuart_init(d)) )
goto fail;
+ if ( (rc = iommu_domain_init(d)) != 0 )
+ goto fail;
+
return 0;
fail:
void arch_domain_destroy(struct domain *d)
{
+ /* IOMMU page table is shared with P2M, always call
+ * iommu_domain_destroy() before p2m_teardown().
+ */
+ iommu_domain_destroy(d);
p2m_teardown(d);
domain_vgic_free(d);
domain_vuart_free(d);
}
/* Map the device in the domain */
-static int map_device(struct domain *d, const struct dt_device_node *dev)
+static int map_device(struct domain *d, struct dt_device_node *dev)
{
unsigned int nirq;
unsigned int naddr;
DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr);
+ if ( dt_device_is_protected(dev) )
+ {
+ DPRINT("%s setup iommu\n", dt_node_full_name(dev));
+ res = iommu_assign_dt_device(d, dev);
+ if ( res )
+ {
+ printk(XENLOG_ERR "Failed to setup the IOMMU for %s\n",
+ dt_node_full_name(dev));
+ return res;
+ }
+ }
+
/* Map IRQs */
for ( i = 0; i < nirq; i++ )
{
}
static int handle_node(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node)
+ struct dt_device_node *node)
{
static const struct dt_device_match skip_matches[] __initconst =
{
DT_MATCH_TIMER,
{ /* sentinel */ },
};
- const struct dt_device_node *child;
+ struct dt_device_node *child;
int res;
const char *name;
const char *path;
printk("*** LOADING DOMAIN 0 ***\n");
+ iommu_hwdom_init(d);
+
d->max_pages = ~0U;
kinfo.unassigned_mem = dom0_mem;
}
if ( flush )
+ {
+ unsigned long sgfn = paddr_to_pfn(start_gpaddr);
+ unsigned long egfn = paddr_to_pfn(end_gpaddr);
+
flush_tlb_domain(d);
+ iommu_iotlb_flush(d, sgfn, egfn - sgfn);
+ }
if ( op == ALLOCATE || op == INSERT )
{
local_irq_enable();
local_abort_enable();
+ iommu_setup();
+
smp_prepare_cpus(cpus);
initialize_keytable();
subdir-$(x86) += vtd
subdir-$(x86) += amd
subdir-$(x86_64) += x86
+subdir-$(arm) += arm
obj-y += iommu.o
obj-$(x86) += io.o
--- /dev/null
+obj-y += iommu.o
--- /dev/null
+/*
+ * Generic IOMMU framework via the device tree
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2014 Linaro Limited.
+ *
+ * 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.
+ */
+
+#include <xen/lib.h>
+#include <xen/iommu.h>
+#include <xen/device_tree.h>
+#include <asm/device.h>
+
+static const struct iommu_ops *iommu_ops;
+
+const struct iommu_ops *iommu_get_ops(void)
+{
+ return iommu_ops;
+}
+
+void __init iommu_set_ops(const struct iommu_ops *ops)
+{
+ BUG_ON(ops == NULL);
+
+ if ( iommu_ops && iommu_ops != ops )
+ printk("WARNING: Cannot set IOMMU ops, already set to a different value\n");
+
+ iommu_ops = ops;
+}
+
+int __init iommu_hardware_setup(void)
+{
+ struct dt_device_node *np;
+ int rc;
+ unsigned int num_iommus = 0;
+
+ dt_for_each_device_node(dt_host, np)
+ {
+ rc = device_init(np, DEVICE_IOMMU, NULL);
+ if ( !rc )
+ num_iommus++;
+ }
+
+ return ( num_iommus > 0 ) ? 0 : -ENODEV;
+}
+
+void __hwdom_init arch_iommu_check_autotranslated_hwdom(struct domain *d)
+{
+ /* ARM doesn't require specific check for hwdom */
+ return;
+}
+
+int arch_iommu_domain_init(struct domain *d)
+{
+ return iommu_dt_domain_init(d);
+}
+
+void arch_iommu_domain_destroy(struct domain *d)
+{
+ iommu_dt_domain_destroy(d);
+}
enum device_type
{
- DEVICE_SERIAL
+ DEVICE_SERIAL,
+ DEVICE_IOMMU,
};
struct device_desc {
#include <asm/vfp.h>
#include <public/hvm/params.h>
#include <xen/serial.h>
+#include <xen/hvm/iommu.h>
/* Represents state corresponding to a block of 32 interrupts */
struct vgic_irq_rank {
struct hvm_domain
{
uint64_t params[HVM_NR_PARAMS];
+ struct hvm_iommu iommu;
} __cacheline_aligned;
#ifdef CONFIG_ARM_64
--- /dev/null
+#ifndef __ASM_ARM_HVM_IOMMU_H_
+#define __ASM_ARM_HVM_IOMMU_H_
+
+struct arch_hvm_iommu
+{
+ /* Private information for the IOMMU drivers */
+ void *priv;
+};
+
+#endif /* __ASM_ARM_HVM_IOMMU_H_ */
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+*/
+#ifndef __ARCH_ARM_IOMMU_H__
+#define __ARCH_ARM_IOMMU_H__
+
+/* Always share P2M Table between the CPU and the IOMMU */
+#define iommu_use_hap_pt(d) (1)
+#define domain_hvm_iommu(d) (&d->arch.hvm_domain.iommu)
+
+const struct iommu_ops *iommu_get_ops(void);
+void __init iommu_set_ops(const struct iommu_ops *ops);
+
+int __init iommu_hardware_setup(void);
+
+#endif /* __ARCH_ARM_IOMMU_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */