Skip to content

Commit

Permalink
iommu/vt-d: Ratelimit fault handler
Browse files Browse the repository at this point in the history
Fault rates can easily overwhelm the console and make the system
unresponsive.  Ratelimit to allow an opportunity for maintenance.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Fixes: 0ac2491 ('x86, dmar: move page fault handling code to dmar.c')
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Alex Williamson authored and Joerg Roedel committed Apr 5, 2016
1 parent 9735a22 commit c43fce4
Showing 1 changed file with 22 additions and 11 deletions.
33 changes: 22 additions & 11 deletions drivers/iommu/dmar.c
Original file line number Diff line number Diff line change
@@ -1602,10 +1602,17 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
int reg, fault_index;
u32 fault_status;
unsigned long flag;
bool ratelimited;
static DEFINE_RATELIMIT_STATE(rs,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);

/* Disable printing, simply clear the fault when ratelimited */
ratelimited = !__ratelimit(&rs);

raw_spin_lock_irqsave(&iommu->register_lock, flag);
fault_status = readl(iommu->reg + DMAR_FSTS_REG);
if (fault_status)
if (fault_status && !ratelimited)
pr_err("DRHD: handling fault status reg %x\n", fault_status);

/* TBD: ignore advanced fault log currently */
@@ -1627,24 +1634,28 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
if (!(data & DMA_FRCD_F))
break;

fault_reason = dma_frcd_fault_reason(data);
type = dma_frcd_type(data);
if (!ratelimited) {
fault_reason = dma_frcd_fault_reason(data);
type = dma_frcd_type(data);

data = readl(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN + 8);
source_id = dma_frcd_source_id(data);
data = readl(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN + 8);
source_id = dma_frcd_source_id(data);

guest_addr = dmar_readq(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN);
guest_addr = dma_frcd_page_addr(guest_addr);
}

guest_addr = dmar_readq(iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN);
guest_addr = dma_frcd_page_addr(guest_addr);
/* clear the fault */
writel(DMA_FRCD_F, iommu->reg + reg +
fault_index * PRIMARY_FAULT_REG_LEN + 12);

raw_spin_unlock_irqrestore(&iommu->register_lock, flag);

dmar_fault_do_one(iommu, type, fault_reason,
source_id, guest_addr);
if (!ratelimited)
dmar_fault_do_one(iommu, type, fault_reason,
source_id, guest_addr);

fault_index++;
if (fault_index >= cap_num_fault_regs(iommu->cap))

0 comments on commit c43fce4

Please sign in to comment.