From: "Suthikulpanit, Suravee" <suravee.suthikulpanit@amd.com>
To: Vasant Hegde <vasant.hegde@amd.com>,
linux-kernel@vger.kernel.org, iommu@lists.linux.dev,
joro@8bytes.org, jgg@nvidia.com
Cc: yi.l.liu@intel.com, kevin.tian@intel.com, nicolinc@nvidia.com,
jon.grimm@amd.com, santosh.shukla@amd.com, Sairaj.K@amd.com,
jay.chen@amd.com, Ming.Shu@amd.com, SooJin.Tan@amd.com,
chrisl@kernel.org, wvw@google.com, wnliu@google.com,
dantuluris@google.com, kpsingh@google.com,
alejandro.j.jimenez@oracle.com, joao.m.martins@oracle.com,
guanghuifeng@linux.alibaba.com
Subject: Re: [PATCH v6 02/24] iommu/amd: Introduce EVENT_TYPE_GUEST_EVENT_FAULT
Date: Thu, 22 Oct 2026 12:32:08 +0700 [thread overview]
Message-ID: <a6e93726-ff61-4f41-8da5-d45e9cfd4fcb@amd.com> (raw)
In-Reply-To: <787b4f08-fd74-4597-8508-fe4ccaf75a24@amd.com>
Vasant,
On 10/19/2026 1:10 PM, Vasant Hegde wrote:
>
>
> On 9/30/2026 2:53 PM, Suravee Suthikulpanit wrote:
>> INSERT_GUEST_EVENT with non-zero reserved bits logs
>> GUEST_EVENT_FAULT followed by the original guest event.
>> Consume both event-log slots, wrapping via
>> evt_buf+(head+EVTLOG_ENTRY_SIZE)%size, and dump the guest
>> payload raw so it is not decoded as a host event.
>>
>> Wait until occupancy is at least two entries, not merely
>> until live tail is not the pair offset. Re-read the
>> event-log tail each poll iteration so a return of 2 cannot
>> advance head past a stale cached tail and walk empty slots
>> with the type-0 erratum retry.
>>
>> Retry a type-0 guest slot up to LOOP_TIMEOUT, the same way
>> erratum 732 waits for the primary slot. Return 2 only when
>> that slot is already in [head, live_tail). Return 1 if the
>> pair never appears in tail. Rate-limit the guest-triggered
>> logs.
>>
>> Log an invalid guest-event when the pair slot is still
>> missing or type 0 after that wait, instead of stalling
>> the event log.
>
>
> As per spec:
> GUEST_EVENT_FAULT event is always written in pairs with a guest event entry
> immediately after it into the event log.
>
> Why not add one additional check in iommu_poll_events() such that:> if event at head is GUEST_EVENT_FAULT and actual fault event is
> not-yet-written by HW just return.
> If subsequent event is also written then handle the event.
>
> and increase head pointer accordingly.
I would like to keep the code for handling GUEST_EVENT_FAULT (including
the logic for checking guest event pair entry) in iommu_print_event() to
simplify the code readability.
Originally, I try to handle the case where the guest event pair may
arrive late, but that adds complexity to the tail polling logic. For v7,
I can simplify the logic to just report GUEST_EVENT_FAULT event with
missing guest eventinstead then.
>> ....
>> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
>> index 43a5690721af..2df81e29519e 100644
>> --- a/drivers/iommu/amd/iommu.c
>> +++ b/drivers/iommu/amd/iommu.c
>> @@ -942,8 +942,18 @@ static void amd_iommu_report_ppr_err(struct amd_iommu *iommu, volatile u32 *even
>> pci_dev_put(pdev);
>> }
>>
>> -static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
>> +static u32 evtlog_used(u32 head, u32 tail)
>> {
>> + return (tail + amd_iommu_evtlog_size - head) % amd_iommu_evtlog_size;
>> +}
>> +
>> +/*
>> + * Decode one event-log slot (or a GUEST_EVENT_FAULT pair).
>> + * Returns the number of slots consumed.
>> + */
>> +static unsigned int iommu_print_event(struct amd_iommu *iommu, u32 head)
>> +{
>> + void *__evt = iommu->evt_buf + head;
>> struct device *dev = iommu->iommu.dev;
>> int type, devid, flags;
>> volatile u32 *event = __evt;
>> @@ -965,7 +975,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
>> /* Did we hit the erratum? */
>> if (++count == LOOP_TIMEOUT) {
>> pr_err("No event written to event log\n");
>> - return;
>> + return 1;
>
> This will cause head to progress event though there is no event.
Actually, there is an event (since the head != tail) but with (type == 0
: invalid event). So, we need to discard the entry and increment head.
>> }
>> udelay(1);
>> goto retry;
>> @@ -975,7 +985,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
>>
>> if (type == EVENT_TYPE_IO_FAULT) {
>> amd_iommu_report_page_fault(iommu, devid, pasid, address, flags, vflags);
>> - return;
>> + return 1;
>> }
>>
>> switch (type) {
>> @@ -1023,9 +1033,90 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
>> case EVENT_TYPE_INV_PPR_REQ:
>> amd_iommu_report_ppr_err(iommu, event, devid, address, flags);
>> break;
>> + case EVENT_TYPE_GUEST_EVENT_FAULT:
>> + {
>> + u16 gid = FIELD_GET(EVENT_GID_MASK, event[1]);
>> + u32 next = (head + EVTLOG_ENTRY_SIZE) % amd_iommu_evtlog_size;
>> + u32 *guest;
>> + u32 live_tail, w0, w1, w2, w3;
>> + int guest_type, wait;
>> +
>> + dev_err_ratelimited(dev, "Event logged [GUEST_EVENT_FAULT gid=%#x flags=0x%04x vflags=%#x]\n",
>> + gid, flags, vflags);
>> +
>> + /*
>> + * GUEST_EVENT_FAULT is paired with the original guest
>> + * event in the next log slot (possibly wrapped). The
>> + * poll-time tail can predate that slot. Wait until
>> + * occupancy is at least two entries, then retry a
>> + * type-0 pair slot the same way erratum 732 waits
>> + * for DMA visibility. Return 2 only when that slot
>> + * is already in [head, live_tail). iommu_poll_events()
>> + * re-reads tail each iteration so head cannot skip
>> + * past tail.
>> + */
>> + wait = 0;
>> + for (;;) {
>> + live_tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
>> + if (evtlog_used(head, live_tail) >=
>> + 2 * EVTLOG_ENTRY_SIZE)
>> + break;
>> + if (++wait == LOOP_TIMEOUT) {
>
> I think we should avoid avoid this loop in interrupt handler path.
I am removing this loop.
>> + dev_err_ratelimited(dev, "Event logged [GUEST_EVENT_FAULT invalid guest-event (does not exist)]\n");
>> + if (!amd_iommu_snp_en)
>> + memset(__evt, 0, EVTLOG_ENTRY_SIZE);
>> + return 1;
>> + }
>> + udelay(1);
>> + }
>> +
>> + guest = (u32 *)(iommu->evt_buf + next);
>> + wait = 0;
>> + for (;;) {
>> + w1 = READ_ONCE(guest[1]);
>> + guest_type = (w1 >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
>> + if (guest_type)
>> + break;
>> + if (++wait == LOOP_TIMEOUT) {
>> + w0 = READ_ONCE(guest[0]);
>> + w2 = READ_ONCE(guest[2]);
>> + w3 = READ_ONCE(guest[3]);
>> + dev_err_ratelimited(dev, "Event logged [GUEST_EVENT_FAULT invalid guest-event %08x %08x %08x %08x]\n",
>> + w0, w1, w2, w3);
>> + if (!amd_iommu_snp_en) {
>> + memset(__evt, 0, EVTLOG_ENTRY_SIZE);
>> + memset(guest, 0, EVTLOG_ENTRY_SIZE);
>> + }
>> + /* Occupancy already includes this slot.
>> + * Skip it so a late DMA fill is not
>> + * decoded as a host event.
>> + */
>> + return 2;
>> + }
>> + udelay(1);
>> + }
>> +
>> + w0 = READ_ONCE(guest[0]);
>> + w2 = READ_ONCE(guest[2]);
>> + w3 = READ_ONCE(guest[3]);
>> + dev_err_ratelimited(dev, "Event logged [GUEST_EVENT_FAULT guest-event %08x %08x %08x %08x]\n",
>> + w0, w1, w2, w3);
>> +
>> + /*
>> + * Erratum 732: clear both pair slots so a stale guest
>> + * event is not decoded on the next poll. The second
>> + * slot may wrap to the start of the ring. Skip on SNP;
>> + * that buffer is not writable.
>> + */
>> + if (!amd_iommu_snp_en) {
>> + memset(__evt, 0, EVTLOG_ENTRY_SIZE);
>> + memset(guest, 0, EVTLOG_ENTRY_SIZE);
>> + }
>> + return 2;
>> + }
>> case EVENT_TYPE_VIOMMU_HW_ERR:
>> {
>> - u16 gid = event[0] & 0xFFFF;
>> + u16 gid = FIELD_GET(EVENT_GID_MASK, event[0]);
>> u8 src = (event[0] >> 16) & 0x3;
>>
>> dev_err(dev, "Event logged [VIOMMU_HW_ERR gid=%#x address=%#llx src=%#x flags=0x%04x vflags=%#x]\n",
>> @@ -1044,24 +1135,27 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
>> * SNP enabled system.
>> */
>> if (!amd_iommu_snp_en)
>> - memset(__evt, 0, 4 * sizeof(u32));
>> + memset(__evt, 0, EVTLOG_ENTRY_SIZE);
>> +
>> + return 1;
>> }
>>
>> static void iommu_poll_events(struct amd_iommu *iommu)
>> {
>> u32 head, tail;
>> + unsigned int n;
>>
>> head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
>> - tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
>> -
>> - while (head != tail) {
>> - iommu_print_event(iommu, iommu->evt_buf + head);
>> + for (;;) {
>> + tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
>
> We should read tail outside the loop. Otherwise we may stuck in interrupt
> handler context for long time and cause softlockups.
I am simplifying this logic.
Thanks,
Suravee
next prev parent reply other threads:[~2026-10-22 5:32 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 9:23 [PATCH v6 00/24] iommu/amd: Introduce AMD Hardware-accelerated Virtualized IOMMU (vIOMMU) Support Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 01/24] iommu/amd: Introduce vIOMMU-specific events and event Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 02/24] iommu/amd: Introduce EVENT_TYPE_GUEST_EVENT_FAULT Suravee Suthikulpanit
2026-10-19 6:10 ` Vasant Hegde
2026-10-22 5:32 ` Suthikulpanit, Suravee [this message]
2026-09-30 9:23 ` [PATCH v6 03/24] iommu/amd: Detect and initialize AMD vIOMMU feature Suravee Suthikulpanit
2026-10-19 6:40 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 04/24] iommu/amd: Introduce IOMMUFD vIOMMU support for AMD Suravee Suthikulpanit
2026-09-30 21:44 ` Nicolin Chen
2026-09-30 9:23 ` [PATCH v6 05/24] iommu/amd: Allocate Guest IDs for IOMMUFD vIOMMU instances Suravee Suthikulpanit
2026-10-19 11:15 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 06/24] iommu/amd: Map vIOMMU VF and VF Control MMIO BARs Suravee Suthikulpanit
2026-10-19 11:28 ` Vasant Hegde
2026-10-19 17:06 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 07/24] iommu/amd: Add support for AMD vIOMMU VF MMIO region Suravee Suthikulpanit
2026-10-19 11:38 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 08/24] iommu/amd: Introduce Reset vMMIO Command Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 09/24] iommu/amd: Introduce and map vIOMMU private IPA region Suravee Suthikulpanit
2026-10-19 14:06 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 10/24] iommu/amd: Pass iommu to device_flush_dte() Suravee Suthikulpanit
2026-10-19 17:14 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 11/24] iommu/amd: Pass iommu and devid to amd_iommu_make_clear_dte() Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 12/24] iommu/amd: Store per-segment iommu_dev_data in an xarray Suravee Suthikulpanit
2026-10-19 13:39 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 13/24] iommu/amd: Program IOMMU DTE with the private IPA domain Suravee Suthikulpanit
2026-10-19 16:58 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 14/24] iommu/amd: Add per-VM private IPA alloc/map helpers Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 15/24] iommu/amd: Add helper functions to manage DevID / DomID mapping tables Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 16/24] iommu/amd: Add IOMMUFD vDevice and DevID mapping Suravee Suthikulpanit
2026-10-15 23:39 ` Jason Gunthorpe
2026-10-21 5:15 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 17/24] iommu/amd: Program nested DTE and DomID map on attach Suravee Suthikulpanit
2026-10-15 23:39 ` Jason Gunthorpe
2026-10-21 5:26 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 18/24] iommu/amd: Init and clear vIOMMU DevID and DomID maps Suravee Suthikulpanit
2026-10-15 23:39 ` Jason Gunthorpe
2026-10-20 16:00 ` Suthikulpanit, Suravee
2026-10-20 16:50 ` Jason Gunthorpe
2026-10-21 5:28 ` Suthikulpanit, Suravee
2026-10-21 5:29 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 19/24] iommu/amd: Add per-segment translate device ID pool Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 20/24] iommu/amd: Reserve translate-device-id for PCI requestor aliases Suravee Suthikulpanit
2026-09-30 9:23 ` [PATCH v6 21/24] iommu/amd: Add translation DTE and VFctrl TransDevID helpers Suravee Suthikulpanit
2026-10-21 6:15 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 22/24] iommu/amd: Add translate-device-id alloc/free with vIOMMU owner Suravee Suthikulpanit
2026-10-21 6:33 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 23/24] iommu/amd: Assign per-vIOMMU translate device ID Suravee Suthikulpanit
2026-10-21 10:06 ` Vasant Hegde
2026-09-30 9:23 ` [PATCH v6 24/24] iommu/amd: Relocate vIOMMU translate-device-id on PCI reserve Suravee Suthikulpanit
2026-10-21 10:09 ` Vasant Hegde
2026-10-15 12:33 ` [PATCH v6 00/24] iommu/amd: Introduce AMD Hardware-accelerated Virtualized IOMMU (vIOMMU) Support Guixin Liu
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=a6e93726-ff61-4f41-8da5-d45e9cfd4fcb@amd.com \
--to=suravee.suthikulpanit@amd.com \
--cc=Ming.Shu@amd.com \
--cc=Sairaj.K@amd.com \
--cc=SooJin.Tan@amd.com \
--cc=alejandro.j.jimenez@oracle.com \
--cc=chrisl@kernel.org \
--cc=dantuluris@google.com \
--cc=guanghuifeng@linux.alibaba.com \
--cc=iommu@lists.linux.dev \
--cc=jay.chen@amd.com \
--cc=jgg@nvidia.com \
--cc=joao.m.martins@oracle.com \
--cc=jon.grimm@amd.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kpsingh@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nicolinc@nvidia.com \
--cc=santosh.shukla@amd.com \
--cc=vasant.hegde@amd.com \
--cc=wnliu@google.com \
--cc=wvw@google.com \
--cc=yi.l.liu@intel.com \
/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.