Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38717946 authored by Kay, Allen M's avatar Kay, Allen M Committed by Avi Kivity
Browse files

VT-d: Changes to support KVM



This patch extends the VT-d driver to support KVM

[Ben: fixed memory pinning]
[avi: move dma_remapping.h as well]

Signed-off-by: default avatarKay, Allen M <allen.m.kay@intel.com>
Signed-off-by: default avatarWeidong Han <weidong.han@intel.com>
Signed-off-by: default avatarBen-Ami Yassour <benami@il.ibm.com>
Signed-off-by: default avatarAmit Shah <amit.shah@qumranet.com>
Acked-by: default avatarMark Gross <mgross@linux.intel.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent aa3a816b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@

#include <linux/pci.h>
#include <linux/dmar.h>
#include <linux/iova.h>
#include <linux/intel-iommu.h>
#include <linux/timer.h>
#include "iova.h"
#include "intel-iommu.h"

#undef PREFIX
#define PREFIX "DMAR:"
+112 −4
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@
#include <linux/dma-mapping.h>
#include <linux/mempool.h>
#include <linux/timer.h>
#include "iova.h"
#include "intel-iommu.h"
#include <linux/iova.h>
#include <linux/intel-iommu.h>
#include <asm/proto.h> /* force_iommu in this header in x86-64*/
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -156,7 +156,7 @@ static inline void *alloc_domain_mem(void)
	return iommu_kmem_cache_alloc(iommu_domain_cache);
}

static inline void free_domain_mem(void *vaddr)
static void free_domain_mem(void *vaddr)
{
	kmem_cache_free(iommu_domain_cache, vaddr);
}
@@ -1341,7 +1341,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
 * find_domain
 * Note: we use struct pci_dev->dev.archdata.iommu stores the info
 */
struct dmar_domain *
static struct dmar_domain *
find_domain(struct pci_dev *pdev)
{
	struct device_domain_info *info;
@@ -2318,3 +2318,111 @@ int __init intel_iommu_init(void)
	return 0;
}

void intel_iommu_domain_exit(struct dmar_domain *domain)
{
	u64 end;

	/* Domain 0 is reserved, so dont process it */
	if (!domain)
		return;

	end = DOMAIN_MAX_ADDR(domain->gaw);
	end = end & (~PAGE_MASK_4K);

	/* clear ptes */
	dma_pte_clear_range(domain, 0, end);

	/* free page tables */
	dma_pte_free_pagetable(domain, 0, end);

	iommu_free_domain(domain);
	free_domain_mem(domain);
}
EXPORT_SYMBOL_GPL(intel_iommu_domain_exit);

struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev)
{
	struct dmar_drhd_unit *drhd;
	struct dmar_domain *domain;
	struct intel_iommu *iommu;

	drhd = dmar_find_matched_drhd_unit(pdev);
	if (!drhd) {
		printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n");
		return NULL;
	}

	iommu = drhd->iommu;
	if (!iommu) {
		printk(KERN_ERR
			"intel_iommu_domain_alloc: iommu == NULL\n");
		return NULL;
	}
	domain = iommu_alloc_domain(iommu);
	if (!domain) {
		printk(KERN_ERR
			"intel_iommu_domain_alloc: domain == NULL\n");
		return NULL;
	}
	if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
		printk(KERN_ERR
			"intel_iommu_domain_alloc: domain_init() failed\n");
		intel_iommu_domain_exit(domain);
		return NULL;
	}
	return domain;
}
EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc);

int intel_iommu_context_mapping(
	struct dmar_domain *domain, struct pci_dev *pdev)
{
	int rc;
	rc = domain_context_mapping(domain, pdev);
	return rc;
}
EXPORT_SYMBOL_GPL(intel_iommu_context_mapping);

int intel_iommu_page_mapping(
	struct dmar_domain *domain, dma_addr_t iova,
	u64 hpa, size_t size, int prot)
{
	int rc;
	rc = domain_page_mapping(domain, iova, hpa, size, prot);
	return rc;
}
EXPORT_SYMBOL_GPL(intel_iommu_page_mapping);

void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
{
	detach_domain_for_dev(domain, bus, devfn);
}
EXPORT_SYMBOL_GPL(intel_iommu_detach_dev);

struct dmar_domain *
intel_iommu_find_domain(struct pci_dev *pdev)
{
	return find_domain(pdev);
}
EXPORT_SYMBOL_GPL(intel_iommu_find_domain);

int intel_iommu_found(void)
{
	return g_num_of_iommus;
}
EXPORT_SYMBOL_GPL(intel_iommu_found);

u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
{
	struct dma_pte *pte;
	u64 pfn;

	pfn = 0;
	pte = addr_to_dma_pte(domain, iova);

	if (pte)
		pfn = dma_pte_addr(*pte);

	return pfn >> PAGE_SHIFT_4K;
}
EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
#include <linux/pci.h>
#include <linux/irq.h>
#include <asm/io_apic.h>
#include "intel-iommu.h"
#include <linux/intel-iommu.h>
#include "intr_remapping.h"

static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
+1 −1
Original line number Diff line number Diff line
#include "intel-iommu.h"
#include <linux/intel-iommu.h>

struct ioapic_scope {
	struct intel_iommu *iommu;
+1 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
 */

#include "iova.h"
#include <linux/iova.h>

void
init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
Loading