From: Jiang Liu <jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
To: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>,
David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
Yinghai Lu <yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Dan Williams
<dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Tony Luck <tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
Jiang Liu <jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Subject: [Patch Part1 V3 01/20] iommu/vt-d: use dedicated bitmap to track remapping entry allocation status
Date: Mon, 6 Jan 2014 14:18:08 +0800 [thread overview]
Message-ID: <1388989107-4795-2-git-send-email-jiang.liu@linux.intel.com> (raw)
In-Reply-To: <1388989107-4795-1-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Currently Intel interrupt remapping drivers uses the "present" flag bit
in remapping entry to track whether an entry is allocated or not.
It works as follow:
1) allocate a remapping entry and set its "present" flag bit to 1
2) compose other fields for the entry
3) update the remapping entry with the composed value
The remapping hardware may access the entry between step 1 and step 3,
which then observers an entry with the "present" flag set but random
values in all other fields.
This patch introduces a dedicated bitmap to track remapping entry
allocation status instead of sharing the "present" flag with hardware,
thus eliminate the race window. It also simplifies the implementation.
Tested-and-reviewed-by: Yijing Wang <wangyijing-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Jiang Liu <jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/iommu/intel_irq_remapping.c | 55 +++++++++++++++++------------------
include/linux/intel-iommu.h | 1 +
2 files changed, 27 insertions(+), 29 deletions(-)
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index bab10b1..deef3d4 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -72,7 +72,6 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
u16 index, start_index;
unsigned int mask = 0;
unsigned long flags;
- int i;
if (!count || !irq_iommu)
return -1;
@@ -96,32 +95,17 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
}
raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
- do {
- for (i = index; i < index + count; i++)
- if (table->base[i].present)
- break;
- /* empty index found */
- if (i == index + count)
- break;
-
- index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
-
- if (index == start_index) {
- raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate an IRTE\n");
- return -1;
- }
- } while (1);
-
- for (i = index; i < index + count; i++)
- table->base[i].present = 1;
-
- cfg->remapped = 1;
- irq_iommu->iommu = iommu;
- irq_iommu->irte_index = index;
- irq_iommu->sub_handle = 0;
- irq_iommu->irte_mask = mask;
-
+ index = bitmap_find_free_region(table->bitmap,
+ INTR_REMAP_TABLE_ENTRIES, mask);
+ if (index < 0) {
+ pr_warn("IR%d: can't allocate an IRTE\n", iommu->seq_id);
+ } else {
+ cfg->remapped = 1;
+ irq_iommu->iommu = iommu;
+ irq_iommu->irte_index = index;
+ irq_iommu->sub_handle = 0;
+ irq_iommu->irte_mask = mask;
+ }
raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return index;
@@ -254,6 +238,8 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
set_64bit(&entry->low, 0);
set_64bit(&entry->high, 0);
}
+ bitmap_release_region(iommu->ir_table->bitmap, index,
+ irq_iommu->irte_mask);
return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
}
@@ -453,6 +439,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
{
struct ir_table *ir_table;
struct page *pages;
+ unsigned long *bitmap;
ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
GFP_ATOMIC);
@@ -464,13 +451,23 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
INTR_REMAP_PAGE_ORDER);
if (!pages) {
- printk(KERN_ERR "failed to allocate pages of order %d\n",
- INTR_REMAP_PAGE_ORDER);
+ pr_err("IR%d: failed to allocate pages of order %d\n",
+ iommu->seq_id, INTR_REMAP_PAGE_ORDER);
kfree(iommu->ir_table);
return -ENOMEM;
}
+ bitmap = kcalloc(BITS_TO_LONGS(INTR_REMAP_TABLE_ENTRIES),
+ sizeof(long), GFP_ATOMIC);
+ if (bitmap == NULL) {
+ pr_err("IR%d: failed to allocate bitmap\n", iommu->seq_id);
+ __free_pages(pages, INTR_REMAP_PAGE_ORDER);
+ kfree(ir_table);
+ return -ENOMEM;
+ }
+
ir_table->base = page_address(pages);
+ ir_table->bitmap = bitmap;
iommu_set_irq_remapping(iommu, mode);
return 0;
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index d380c5e..de1e5e9 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -288,6 +288,7 @@ struct q_inval {
struct ir_table {
struct irte *base;
+ unsigned long *bitmap;
};
#endif
--
1.7.10.4
WARNING: multiple messages have this Message-ID (diff)
From: Jiang Liu <jiang.liu@linux.intel.com>
To: Joerg Roedel <joro@8bytes.org>,
David Woodhouse <dwmw2@infradead.org>,
Yinghai Lu <yinghai@kernel.org>,
Dan Williams <dan.j.williams@intel.com>,
Vinod Koul <vinod.koul@intel.com>
Cc: Jiang Liu <jiang.liu@linux.intel.com>,
Ashok Raj <ashok.raj@intel.com>,
Yijing Wang <wangyijing@huawei.com>,
Tony Luck <tony.luck@intel.com>,
iommu@lists.linux-foundation.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org
Subject: [Patch Part1 V3 01/20] iommu/vt-d: use dedicated bitmap to track remapping entry allocation status
Date: Mon, 6 Jan 2014 14:18:08 +0800 [thread overview]
Message-ID: <1388989107-4795-2-git-send-email-jiang.liu@linux.intel.com> (raw)
In-Reply-To: <1388989107-4795-1-git-send-email-jiang.liu@linux.intel.com>
Currently Intel interrupt remapping drivers uses the "present" flag bit
in remapping entry to track whether an entry is allocated or not.
It works as follow:
1) allocate a remapping entry and set its "present" flag bit to 1
2) compose other fields for the entry
3) update the remapping entry with the composed value
The remapping hardware may access the entry between step 1 and step 3,
which then observers an entry with the "present" flag set but random
values in all other fields.
This patch introduces a dedicated bitmap to track remapping entry
allocation status instead of sharing the "present" flag with hardware,
thus eliminate the race window. It also simplifies the implementation.
Tested-and-reviewed-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
drivers/iommu/intel_irq_remapping.c | 55 +++++++++++++++++------------------
include/linux/intel-iommu.h | 1 +
2 files changed, 27 insertions(+), 29 deletions(-)
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index bab10b1..deef3d4 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -72,7 +72,6 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
u16 index, start_index;
unsigned int mask = 0;
unsigned long flags;
- int i;
if (!count || !irq_iommu)
return -1;
@@ -96,32 +95,17 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
}
raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
- do {
- for (i = index; i < index + count; i++)
- if (table->base[i].present)
- break;
- /* empty index found */
- if (i == index + count)
- break;
-
- index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
-
- if (index == start_index) {
- raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate an IRTE\n");
- return -1;
- }
- } while (1);
-
- for (i = index; i < index + count; i++)
- table->base[i].present = 1;
-
- cfg->remapped = 1;
- irq_iommu->iommu = iommu;
- irq_iommu->irte_index = index;
- irq_iommu->sub_handle = 0;
- irq_iommu->irte_mask = mask;
-
+ index = bitmap_find_free_region(table->bitmap,
+ INTR_REMAP_TABLE_ENTRIES, mask);
+ if (index < 0) {
+ pr_warn("IR%d: can't allocate an IRTE\n", iommu->seq_id);
+ } else {
+ cfg->remapped = 1;
+ irq_iommu->iommu = iommu;
+ irq_iommu->irte_index = index;
+ irq_iommu->sub_handle = 0;
+ irq_iommu->irte_mask = mask;
+ }
raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
return index;
@@ -254,6 +238,8 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
set_64bit(&entry->low, 0);
set_64bit(&entry->high, 0);
}
+ bitmap_release_region(iommu->ir_table->bitmap, index,
+ irq_iommu->irte_mask);
return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
}
@@ -453,6 +439,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
{
struct ir_table *ir_table;
struct page *pages;
+ unsigned long *bitmap;
ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
GFP_ATOMIC);
@@ -464,13 +451,23 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
INTR_REMAP_PAGE_ORDER);
if (!pages) {
- printk(KERN_ERR "failed to allocate pages of order %d\n",
- INTR_REMAP_PAGE_ORDER);
+ pr_err("IR%d: failed to allocate pages of order %d\n",
+ iommu->seq_id, INTR_REMAP_PAGE_ORDER);
kfree(iommu->ir_table);
return -ENOMEM;
}
+ bitmap = kcalloc(BITS_TO_LONGS(INTR_REMAP_TABLE_ENTRIES),
+ sizeof(long), GFP_ATOMIC);
+ if (bitmap == NULL) {
+ pr_err("IR%d: failed to allocate bitmap\n", iommu->seq_id);
+ __free_pages(pages, INTR_REMAP_PAGE_ORDER);
+ kfree(ir_table);
+ return -ENOMEM;
+ }
+
ir_table->base = page_address(pages);
+ ir_table->bitmap = bitmap;
iommu_set_irq_remapping(iommu, mode);
return 0;
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index d380c5e..de1e5e9 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -288,6 +288,7 @@ struct q_inval {
struct ir_table {
struct irte *base;
+ unsigned long *bitmap;
};
#endif
--
1.7.10.4
next prev parent reply other threads:[~2014-01-06 6:18 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-06 6:18 [Patch Part1 V3 00/20] Bugfixes and improvements for Intel IOMMU drivers Jiang Liu
2014-01-06 6:18 ` Jiang Liu
[not found] ` <1388989107-4795-1-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-01-06 6:18 ` Jiang Liu [this message]
2014-01-06 6:18 ` [Patch Part1 V3 01/20] iommu/vt-d: use dedicated bitmap to track remapping entry allocation status Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 02/20] iommu/vt-d: fix PCI device reference leakage on error recovery path Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-08 8:53 ` [PATCH] iommu/vt-d: fix compilation error when CONFIG_INTEL_IOMMU is unset Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 03/20] iommu/vt-d: fix a race window in allocating domain ID for virtual machines Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 04/20] iommu/vt-d: fix resource leakage on error recovery path in iommu_init_domains() Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 05/20] iommu/vt-d, trivial: refine support of 64bit guest address Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 06/20] iommu/vt-d, trivial: print correct domain id of static identity domain Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 07/20] iommu/vt-d, trivial: check suitable flag in function detect_intel_iommu() Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 08/20] iommu/vt-d, trivial: clean up unused code Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 09/20] iommu/vt-d: mark internal functions as static Jiang Liu
2014-01-06 6:18 ` Jiang Liu
[not found] ` <1388989107-4795-10-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-01-07 15:25 ` Joerg Roedel
2014-01-07 15:25 ` Joerg Roedel
[not found] ` <20140107152523.GG2742-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2014-01-08 8:44 ` Jiang Liu
2014-01-08 8:44 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 10/20] iommu/vt-d, trivial: use defined macro instead of hardcoding Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 11/20] iommu/vt-d, trivial: simplify code with existing macros Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 12/20] iommu/vt-d: fix invalid memory access when freeing DMAR irq Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 13/20] iommu/vt-d: keep shared resources when failed to initialize iommu devices Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 14/20] iommu/vt-d: avoid double free in error recovery path Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 15/20] iommu/vt-d: fix access after free issue in function free_dmar_iommu() Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 16/20] iommu/vt-d: release invalidation queue when destroying IOMMU unit Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 17/20] iommu/vt-d: fix wrong return value of dmar_table_init() Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 18/20] iommu/vt-d, PCI, trivial: use dev_is_pci() instead of hardcoding Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 19/20] iommu/vt-d, trivial: clean sparse warnings Jiang Liu
2014-01-06 6:18 ` Jiang Liu
[not found] ` <1388989107-4795-20-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-01-08 8:57 ` [PATCH] iommu/vt-d: fix compilation error for IA64 platform Jiang Liu
2014-01-08 8:57 ` Jiang Liu
[not found] ` <1389171427-26223-1-git-send-email-jiang.liu-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-01-09 11:55 ` Joerg Roedel
2014-01-09 11:55 ` Joerg Roedel
[not found] ` <20140109115501.GI29041-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2014-01-10 1:39 ` Jiang Liu
2014-01-10 1:39 ` Jiang Liu
2014-01-06 6:18 ` [Patch Part1 V3 20/20] iommu/vt-d: free all resources if failed to initialize DMARs Jiang Liu
2014-01-06 6:18 ` Jiang Liu
2014-01-07 16:09 ` [Patch Part1 V3 00/20] Bugfixes and improvements for Intel IOMMU drivers Joerg Roedel
2014-01-07 16:09 ` Joerg Roedel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1388989107-4795-2-git-send-email-jiang.liu@linux.intel.com \
--to=jiang.liu-vuqaysv1563yd54fqh9/ca@public.gmane.org \
--cc=dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org \
--cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.