From: Farhan Ali <alifm@linux.ibm.com>
To: Konstantin Shkolnyy <kshk@linux.ibm.com>, mjrosato@linux.ibm.com
Cc: richard.henderson@linaro.org, iii@linux.ibm.com,
david@kernel.org, cohuck@redhat.com, pasic@linux.ibm.com,
borntraeger@linux.ibm.com, qemu-s390x@nongnu.org,
qemu-devel@nongnu.org
Subject: Re: [PATCH v4 14/15] s390x/pci: Implement migration for emulated devices
Date: Tue, 28 Jul 2026 14:29:31 -0700 [thread overview]
Message-ID: <cd95e362-56b6-4e1f-ae8b-287db5fbb41d@linux.ibm.com> (raw)
In-Reply-To: <bd784407-06a3-47fc-8c13-4e3d70e856b5@linux.ibm.com>
On 7/28/2026 1:59 PM, Konstantin Shkolnyy wrote:
> On 260728 12:46, Farhan Ali wrote:
>>
>> On 7/27/2026 4:23 PM, Konstantin Shkolnyy wrote:
>>>>> +static int s390_pci_device_pre_load(void *opaque)
>>>>> +{
>>>>> + S390PCIBusDevice *pbdev = S390_PCI_DEVICE(opaque);
>>>>> + S390PCIBusDevice *found_pbdev;
>>>>> +
>>>>> + /*
>>>>> + * Make sure pbdev is removed from the table before state
>>>>> load. The change
>>>>> + * of pbdev->idx means it needs to be moved to a different
>>>>> position anyway,
>>>>> + * and is illegal while in the table. But be careful to not
>>>>> remove
>>>>> + * instead another pbdev whose state might have been loaded
>>>>> earlier and
>>>>
>>>> I think "instead" is not needed in the statement above.
>>>>
>>>> Maybe I am missing something, but could you help me understand why
>>>> do we need to remove the pbdev if we found at a particular idx? If
>>>> there is a collision with idx, ie on destination we have a
>>>> different device with the same idx, are we removing a valid device?
>>>
>>> I see that this is not the best comment. How about this variant:
>>>
>>> * State loading can change pbdev->idx. Therefore, make sure
>>> pbdev is removed
>>> * from the table before that happens. The table type used stores
>>> a pointer
>>> * to pbdev->idx and becomes corrupt if idx is changed from
>>> outside. But be
>>> * careful to not remove instead another pbdev whose state might
>>> have been
>>> * loaded earlier and that got assigned this idx value and had
>>> therefore
>>> * already replaced our pbdev in the table. post_load() will
>>> reinsert our
>>> * pbdev into the table.
>>>
>> So pbdev->idx is autogenerated when we create the device at
>> destination, since we are migrating the idx from source this could
>> change on destination and corrupt the hash table?
>
> Exactly.
>
> Then do we need to migrate the idx?
>>
>
> idx is part of "function handle". So, it should remain unchanged after
> migration.
>
>>
>>>>
>>>>> + * that has then replaced our pbdev. (post_load() will put
>>>>> our pbdev back.)
>>>>> + */
>>>>> + found_pbdev = g_hash_table_lookup(s390_get_phb()->zpci_table,
>>>>> &pbdev->idx);
>>>>> + assert(found_pbdev);
>> AFAIU the pbdev->idx at pre_load() would be what we assign
>> automatically at the destination. In that case wouldn't this assert
>> always be true?
>
> Yes. This assert documents that a pbdev is always expected to be found
> for this "autogenerated when we create the device at destination"
> pbdev->idx - either the pbdev we are currently processing, or another
> pbdev that was "loaded" earlier with the same idx value (which came
> from the source) and inserted by post_load() into zpci_table.
>>
>>
>>>>> + if (found_pbdev == pbdev) {
>>
>> similarly this should also be true?
>
> No always true, as described above.
>
Okay this makes a lot more sense to me now, thanks for the explanation!
>>
>>
>>>>> + g_hash_table_remove(s390_get_phb()->zpci_table, &pbdev->idx);
>>
>> Don't we have to free this idx now? so reverse of s390_pci_alloc_idx()?
>
> AFA I can see, simply removing pbdev->idx from zpci_table already
> "frees" the idx value for reuse. s390_pci_alloc_idx() interprets
> s->next_idx as the "next mostly likely free" idx value. It then checks
> if zpci_table has this idx; if it does, it checks idx+1, etc. until it
> doesn't.
>
> It seems, we could add "s->next_idx = pbdev->idx;" here to make it
> pick this idx next time instead of larger values, but it's not
> strictly necessary. Do you think we should do it?
We seem to be doing it in s390_pci_interp_plug() [1] so maybe we should
just to close this gap? In reality though this "leak" is not a concern
for resource exhaustion.
[1]
https://elixir.bootlin.com/qemu/v11.1.0-rc1/source/hw/s390x/s390-pci-bus.c#L1072
Thanks
Farhan
>
>>
>>
>>>>> + }
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static int s390_pci_device_post_load(void *opaque, int version_id)
>>>>> +{
>>>>> + S390PCIBusDevice *pbdev = S390_PCI_DEVICE(opaque);
>>>>> +
>>>>> /*
>>>>> - * TODO: add state handling here, so migration works at least
>>>>> with
>>>>> - * emulated pci devices on s390x
>>>>> + * Now that pbdev->idx has been loaded, use it to place pbdev
>>>>> back into
>>>>> + * the table. This may replace a different
>>>>> not-yet-state-loaded pbdev,
>>>>> + * but pre_load() handles this case.
>>>>> */
>>>>> - .unmigratable = 1,
>>>>> + g_hash_table_replace(s390_get_phb()->zpci_table, &pbdev->idx,
>>>>> pbdev);
>>>>> +
>>>>> + /*
>>>>> + * Regenerate IOMMU state, including IOTLB contents and QEMU
>>>>> memory regions.
>>>>> + */
>>>>> + if (pbdev->iommu_enabled) {
>>>>> + assert(pbdev->iommu);
>>>>> + if (s390_pci_is_translation_enabled(pbdev->g_iota)) {
>>>>> + s390_pci_iommu_enable(pbdev);
>>>>> + s390_pci_ioat_replay(pbdev);
>>>>> + } else {
>>>>> + s390_pci_iommu_direct_map_enable(pbdev);
>>>>> + }
>>>>> + }
>>>>> +
>>>>> + /*
>>>>> + * Guest sets fmb_addr by mpcifc.ZPCI_MOD_FC_SET_MEASURE
>>>>> instruction,
>>>>> + * whose handler consequently starts fmb_timer. We may need
>>>>> to restart it.
>>>>> + */
>>>>> + if (pbdev->fmb_addr) {
>>>>> + assert(!pbdev->fmb_timer);
>>>>> + assert(pbdev->pci_group);
>>>>> + pbdev->fmb_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
>>>>> + fmb_update, pbdev);
>>>>> + timer_mod(pbdev->fmb_timer,
>>>>> + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
>>>>> + pbdev->pci_group->zpci_group.mui);
>>>>> + }
>>>>> + return 0;
>>>>> +}
>
next prev parent reply other threads:[~2026-07-28 21:30 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 3:09 [PATCH v4 00/15] s390x/pci: Implement migration for emulated devices Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 01/15] s390x/pci: implement IOMMU replay Konstantin Shkolnyy
2026-07-24 19:10 ` Farhan Ali
2026-07-24 19:37 ` Matthew Rosato
2026-07-24 3:09 ` [PATCH v4 02/15] s390x/pci: Create function to contain translation status check Konstantin Shkolnyy
2026-07-24 19:11 ` Farhan Ali
2026-07-24 3:09 ` [PATCH v4 03/15] s390x/pci: Move iommu_mr from S390PCIIOMMU to S390PCIBusDevice Konstantin Shkolnyy
2026-07-24 19:26 ` Farhan Ali
2026-07-24 3:09 ` [PATCH v4 04/15] s390x/pci: Move dm_mr " Konstantin Shkolnyy
2026-07-24 19:42 ` Farhan Ali
2026-07-24 3:09 ` [PATCH v4 05/15] s390x/pci: Move iotlb " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 06/15] s390x/pci: Remove a ptr to S390PCIBusDevice from S390PCIIOMMU Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 07/15] s390x/pci: Move/rename enabled from S390PCIIOMMU to S390PCIBusDevice Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 08/15] s390x/pci: Move dma_limit " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 09/15] s390x/pci: Move g_iota " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 10/15] s390x/pci: Move pba " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 11/15] s390x/pci: Move pal " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 12/15] s390x/pci: Move max_dma_limit " Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 13/15] s390x/pci: Add a comment explaining S390PCIIOMMU purpose Konstantin Shkolnyy
2026-07-24 3:09 ` [PATCH v4 14/15] s390x/pci: Implement migration for emulated devices Konstantin Shkolnyy
2026-07-27 18:53 ` Farhan Ali
2026-07-27 23:23 ` Konstantin Shkolnyy
2026-07-28 17:46 ` Farhan Ali
2026-07-28 20:59 ` Konstantin Shkolnyy
2026-07-28 21:29 ` Farhan Ali [this message]
2026-07-24 3:09 ` [PATCH v4 15/15] s390x/pci: Create function to contain fmb_timer start Konstantin Shkolnyy
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=cd95e362-56b6-4e1f-ae8b-287db5fbb41d@linux.ibm.com \
--to=alifm@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=cohuck@redhat.com \
--cc=david@kernel.org \
--cc=iii@linux.ibm.com \
--cc=kshk@linux.ibm.com \
--cc=mjrosato@linux.ibm.com \
--cc=pasic@linux.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=richard.henderson@linaro.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.