aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakao Indoh <indou.takao@jp.fujitsu.com>2013-04-23 04:35:03 -0400
committerJoerg Roedel <joro@8bytes.org>2013-04-23 08:47:08 -0400
commit3a93c841c2b3b14824f7728dd74bd00a1cedb806 (patch)
tree7b4a66f8caceac55b0832b635d537f7a04126eae
parent35d3d814cbd46a85bed97cd74ba97fbbb51e0ccd (diff)
iommu/vt-d: Disable translation if already enabled
This patch disables translation(dma-remapping) before its initialization if it is already enabled. This is needed for kexec/kdump boot. If dma-remapping is enabled in the first kernel, it need to be disabled before initializing its page table during second kernel boot. Wei Hu also reported that this is needed when second kernel boots with intel_iommu=off. Basically iommu->gcmd is used to know whether translation is enabled or disabled, but it is always zero at boot time even when translation is enabled since iommu->gcmd is initialized without considering such a case. Therefor this patch synchronizes iommu->gcmd value with global command register when iommu structure is allocated. Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
-rw-r--r--drivers/iommu/dmar.c11
-rw-r--r--drivers/iommu/intel-iommu.c15
2 files changed, 25 insertions, 1 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 9f8aa07360ba..f7890edb22f5 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -645,7 +645,7 @@ out:
645int alloc_iommu(struct dmar_drhd_unit *drhd) 645int alloc_iommu(struct dmar_drhd_unit *drhd)
646{ 646{
647 struct intel_iommu *iommu; 647 struct intel_iommu *iommu;
648 u32 ver; 648 u32 ver, sts;
649 static int iommu_allocated = 0; 649 static int iommu_allocated = 0;
650 int agaw = 0; 650 int agaw = 0;
651 int msagaw = 0; 651 int msagaw = 0;
@@ -695,6 +695,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
695 (unsigned long long)iommu->cap, 695 (unsigned long long)iommu->cap,
696 (unsigned long long)iommu->ecap); 696 (unsigned long long)iommu->ecap);
697 697
698 /* Reflect status in gcmd */
699 sts = readl(iommu->reg + DMAR_GSTS_REG);
700 if (sts & DMA_GSTS_IRES)
701 iommu->gcmd |= DMA_GCMD_IRE;
702 if (sts & DMA_GSTS_TES)
703 iommu->gcmd |= DMA_GCMD_TE;
704 if (sts & DMA_GSTS_QIES)
705 iommu->gcmd |= DMA_GCMD_QIE;
706
698 raw_spin_lock_init(&iommu->register_lock); 707 raw_spin_lock_init(&iommu->register_lock);
699 708
700 drhd->iommu = iommu; 709 drhd->iommu = iommu;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0099667a397e..414d2d20dd59 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3665,6 +3665,7 @@ static struct notifier_block device_nb = {
3665int __init intel_iommu_init(void) 3665int __init intel_iommu_init(void)
3666{ 3666{
3667 int ret = 0; 3667 int ret = 0;
3668 struct dmar_drhd_unit *drhd;
3668 3669
3669 /* VT-d is required for a TXT/tboot launch, so enforce that */ 3670 /* VT-d is required for a TXT/tboot launch, so enforce that */
3670 force_on = tboot_force_iommu(); 3671 force_on = tboot_force_iommu();
@@ -3675,6 +3676,20 @@ int __init intel_iommu_init(void)
3675 return -ENODEV; 3676 return -ENODEV;
3676 } 3677 }
3677 3678
3679 /*
3680 * Disable translation if already enabled prior to OS handover.
3681 */
3682 for_each_drhd_unit(drhd) {
3683 struct intel_iommu *iommu;
3684
3685 if (drhd->ignored)
3686 continue;
3687
3688 iommu = drhd->iommu;
3689 if (iommu->gcmd & DMA_GCMD_TE)
3690 iommu_disable_translation(iommu);
3691 }
3692
3678 if (dmar_dev_scope_init() < 0) { 3693 if (dmar_dev_scope_init() < 0) {
3679 if (force_on) 3694 if (force_on)
3680 panic("tboot: Failed to initialize DMAR device scope\n"); 3695 panic("tboot: Failed to initialize DMAR device scope\n");