diff options
author | Fenghua Yu <fenghua.yu@intel.com> | 2009-04-24 20:30:20 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-04-29 01:54:34 -0400 |
commit | 4ed0d3e6c64cfd9ba4ceb2099b10d1cf8ece4320 (patch) | |
tree | 950bacfaf57040aafbcc2ea9b52eb171d35c23bd /drivers/pci/dmar.c | |
parent | 091069740304c979f957ceacec39c461d0192158 (diff) |
Intel IOMMU Pass Through Support
The patch adds kernel parameter intel_iommu=pt to set up pass through
mode in context mapping entry. This disables DMAR in linux kernel; but
KVM still runs on VT-d and interrupt remapping still works.
In this mode, kernel uses swiotlb for DMA API functions but other VT-d
functionalities are enabled for KVM. KVM always uses multi level
translation page table in VT-d. By default, pass though mode is disabled
in kernel.
This is useful when people don't want to enable VT-d DMAR in kernel but
still want to use KVM and interrupt remapping for reasons like DMAR
performance concern or debug purpose.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Acked-by: Weidong Han <weidong@intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r-- | drivers/pci/dmar.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index fa3a11365ec3..d3d86b749eee 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -515,6 +515,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
515 | u32 ver; | 515 | u32 ver; |
516 | static int iommu_allocated = 0; | 516 | static int iommu_allocated = 0; |
517 | int agaw = 0; | 517 | int agaw = 0; |
518 | int msagaw = 0; | ||
518 | 519 | ||
519 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | 520 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); |
520 | if (!iommu) | 521 | if (!iommu) |
@@ -535,12 +536,20 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
535 | agaw = iommu_calculate_agaw(iommu); | 536 | agaw = iommu_calculate_agaw(iommu); |
536 | if (agaw < 0) { | 537 | if (agaw < 0) { |
537 | printk(KERN_ERR | 538 | printk(KERN_ERR |
538 | "Cannot get a valid agaw for iommu (seq_id = %d)\n", | 539 | "Cannot get a valid agaw for iommu (seq_id = %d)\n", |
540 | iommu->seq_id); | ||
541 | goto error; | ||
542 | } | ||
543 | msagaw = iommu_calculate_max_sagaw(iommu); | ||
544 | if (msagaw < 0) { | ||
545 | printk(KERN_ERR | ||
546 | "Cannot get a valid max agaw for iommu (seq_id = %d)\n", | ||
539 | iommu->seq_id); | 547 | iommu->seq_id); |
540 | goto error; | 548 | goto error; |
541 | } | 549 | } |
542 | #endif | 550 | #endif |
543 | iommu->agaw = agaw; | 551 | iommu->agaw = agaw; |
552 | iommu->msagaw = msagaw; | ||
544 | 553 | ||
545 | /* the registers might be more than one page */ | 554 | /* the registers might be more than one page */ |
546 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), | 555 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), |