diff options
author | Joerg Roedel <jroedel@suse.de> | 2017-05-15 10:25:03 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2017-05-30 05:44:19 -0400 |
commit | 30bf2df65b0d18f53ee9c92131239f66c8f55d63 (patch) | |
tree | 4200b608021216be069a1800f3eef9f14410bc64 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff) |
iommu/amd: Ratelimit io-page-faults per device
Misbehaving devices can cause an endless chain of
io-page-faults, flooding dmesg and making the system-log
unusable or even prevent the system from booting.
So ratelimit the error messages about io-page-faults on a
per-device basis.
Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r-- | drivers/iommu/amd_iommu.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 63cacf5d6cf2..d3ff766a8ca6 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -138,6 +138,8 @@ struct iommu_dev_data { | |||
138 | PPR completions */ | 138 | PPR completions */ |
139 | u32 errata; /* Bitmap for errata to apply */ | 139 | u32 errata; /* Bitmap for errata to apply */ |
140 | bool use_vapic; /* Enable device to use vapic mode */ | 140 | bool use_vapic; /* Enable device to use vapic mode */ |
141 | |||
142 | struct ratelimit_state rs; /* Ratelimit IOPF messages */ | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | /* | 145 | /* |
@@ -253,6 +255,8 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid) | |||
253 | list_add_tail(&dev_data->dev_data_list, &dev_data_list); | 255 | list_add_tail(&dev_data->dev_data_list, &dev_data_list); |
254 | spin_unlock_irqrestore(&dev_data_list_lock, flags); | 256 | spin_unlock_irqrestore(&dev_data_list_lock, flags); |
255 | 257 | ||
258 | ratelimit_default_init(&dev_data->rs); | ||
259 | |||
256 | return dev_data; | 260 | return dev_data; |
257 | } | 261 | } |
258 | 262 | ||
@@ -551,6 +555,29 @@ static void dump_command(unsigned long phys_addr) | |||
551 | pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); | 555 | pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); |
552 | } | 556 | } |
553 | 557 | ||
558 | static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, | ||
559 | u64 address, int flags) | ||
560 | { | ||
561 | struct iommu_dev_data *dev_data = NULL; | ||
562 | struct pci_dev *pdev; | ||
563 | |||
564 | pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff); | ||
565 | if (pdev) | ||
566 | dev_data = get_dev_data(&pdev->dev); | ||
567 | |||
568 | if (dev_data && __ratelimit(&dev_data->rs)) { | ||
569 | dev_err(&pdev->dev, "AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%016llx flags=0x%04x]\n", | ||
570 | domain_id, address, flags); | ||
571 | } else if (printk_ratelimit()) { | ||
572 | pr_err("AMD-Vi: Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%016llx flags=0x%04x]\n", | ||
573 | PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), | ||
574 | domain_id, address, flags); | ||
575 | } | ||
576 | |||
577 | if (pdev) | ||
578 | pci_dev_put(pdev); | ||
579 | } | ||
580 | |||
554 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) | 581 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) |
555 | { | 582 | { |
556 | int type, devid, domid, flags; | 583 | int type, devid, domid, flags; |
@@ -575,7 +602,12 @@ retry: | |||
575 | goto retry; | 602 | goto retry; |
576 | } | 603 | } |
577 | 604 | ||
578 | printk(KERN_ERR "AMD-Vi: Event logged ["); | 605 | if (type == EVENT_TYPE_IO_FAULT) { |
606 | amd_iommu_report_page_fault(devid, domid, address, flags); | ||
607 | return; | ||
608 | } else { | ||
609 | printk(KERN_ERR "AMD-Vi: Event logged ["); | ||
610 | } | ||
579 | 611 | ||
580 | switch (type) { | 612 | switch (type) { |
581 | case EVENT_TYPE_ILL_DEV: | 613 | case EVENT_TYPE_ILL_DEV: |
@@ -585,12 +617,6 @@ retry: | |||
585 | address, flags); | 617 | address, flags); |
586 | dump_dte_entry(devid); | 618 | dump_dte_entry(devid); |
587 | break; | 619 | break; |
588 | case EVENT_TYPE_IO_FAULT: | ||
589 | printk("IO_PAGE_FAULT device=%02x:%02x.%x " | ||
590 | "domain=0x%04x address=0x%016llx flags=0x%04x]\n", | ||
591 | PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), | ||
592 | domid, address, flags); | ||
593 | break; | ||
594 | case EVENT_TYPE_DEV_TAB_ERR: | 620 | case EVENT_TYPE_DEV_TAB_ERR: |
595 | printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " | 621 | printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " |
596 | "address=0x%016llx flags=0x%04x]\n", | 622 | "address=0x%016llx flags=0x%04x]\n", |