Skip to content

Commit 457da57

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Lock DTE before updating the entry with WRITE_ONCE()
When updating only within a 64-bit tuple of a DTE, just lock the DTE and use WRITE_ONCE() because it is writing to memory read back by HW. Suggested-by: Jason Gunthorpe <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Suravee Suthikulpanit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 66ea3f9 commit 457da57

File tree

2 files changed

+25
-19
lines changed

2 files changed

+25
-19
lines changed

drivers/iommu/amd/amd_iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,4 @@ struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
186186
#endif
187187

188188
struct dev_table_entry *amd_iommu_get_ivhd_dte_flags(u16 segid, u16 devid);
189+
struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid);

drivers/iommu/amd/iommu.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ static struct iommu_dev_data *alloc_dev_data(struct amd_iommu *iommu, u16 devid)
347347
return dev_data;
348348
}
349349

350-
static struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid)
350+
struct iommu_dev_data *search_dev_data(struct amd_iommu *iommu, u16 devid)
351351
{
352352
struct iommu_dev_data *dev_data;
353353
struct llist_node *node;
@@ -2845,12 +2845,12 @@ static int amd_iommu_set_dirty_tracking(struct iommu_domain *domain,
28452845
bool enable)
28462846
{
28472847
struct protection_domain *pdomain = to_pdomain(domain);
2848-
struct dev_table_entry *dev_table;
2848+
struct dev_table_entry *dte;
28492849
struct iommu_dev_data *dev_data;
28502850
bool domain_flush = false;
28512851
struct amd_iommu *iommu;
28522852
unsigned long flags;
2853-
u64 pte_root;
2853+
u64 new;
28542854

28552855
spin_lock_irqsave(&pdomain->lock, flags);
28562856
if (!(pdomain->dirty_tracking ^ enable)) {
@@ -2859,16 +2859,15 @@ static int amd_iommu_set_dirty_tracking(struct iommu_domain *domain,
28592859
}
28602860

28612861
list_for_each_entry(dev_data, &pdomain->dev_list, list) {
2862+
spin_lock(&dev_data->dte_lock);
28622863
iommu = get_amd_iommu_from_dev_data(dev_data);
2863-
2864-
dev_table = get_dev_table(iommu);
2865-
pte_root = dev_table[dev_data->devid].data[0];
2866-
2867-
pte_root = (enable ? pte_root | DTE_FLAG_HAD :
2868-
pte_root & ~DTE_FLAG_HAD);
2864+
dte = &get_dev_table(iommu)[dev_data->devid];
2865+
new = dte->data[0];
2866+
new = (enable ? new | DTE_FLAG_HAD : new & ~DTE_FLAG_HAD);
2867+
dte->data[0] = new;
2868+
spin_unlock(&dev_data->dte_lock);
28692869

28702870
/* Flush device DTE */
2871-
dev_table[dev_data->devid].data[0] = pte_root;
28722871
device_flush_dte(dev_data);
28732872
domain_flush = true;
28742873
}
@@ -3135,17 +3134,23 @@ static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
31353134
static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid,
31363135
struct irq_remap_table *table)
31373136
{
3138-
u64 dte;
3139-
struct dev_table_entry *dev_table = get_dev_table(iommu);
3137+
u64 new;
3138+
struct dev_table_entry *dte = &get_dev_table(iommu)[devid];
3139+
struct iommu_dev_data *dev_data = search_dev_data(iommu, devid);
3140+
3141+
if (dev_data)
3142+
spin_lock(&dev_data->dte_lock);
31403143

3141-
dte = dev_table[devid].data[2];
3142-
dte &= ~DTE_IRQ_PHYS_ADDR_MASK;
3143-
dte |= iommu_virt_to_phys(table->table);
3144-
dte |= DTE_IRQ_REMAP_INTCTL;
3145-
dte |= DTE_INTTABLEN;
3146-
dte |= DTE_IRQ_REMAP_ENABLE;
3144+
new = READ_ONCE(dte->data[2]);
3145+
new &= ~DTE_IRQ_PHYS_ADDR_MASK;
3146+
new |= iommu_virt_to_phys(table->table);
3147+
new |= DTE_IRQ_REMAP_INTCTL;
3148+
new |= DTE_INTTABLEN;
3149+
new |= DTE_IRQ_REMAP_ENABLE;
3150+
WRITE_ONCE(dte->data[2], new);
31473151

3148-
dev_table[devid].data[2] = dte;
3152+
if (dev_data)
3153+
spin_unlock(&dev_data->dte_lock);
31493154
}
31503155

31513156
static struct irq_remap_table *get_irq_table(struct amd_iommu *iommu, u16 devid)

0 commit comments

Comments
 (0)