From: Chenyi Qiang <chenyi.qiang@intel.com>
To: "Gupta, Pankaj" <pankaj.gupta@amd.com>,
"David Hildenbrand" <david@redhat.com>,
"Alexey Kardashevskiy" <aik@amd.com>,
"Peter Xu" <peterx@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Michael Roth" <michael.roth@amd.com>
Cc: <qemu-devel@nongnu.org>, <kvm@vger.kernel.org>,
Williams Dan J <dan.j.williams@intel.com>,
Peng Chao P <chao.p.peng@intel.com>,
Gao Chao <chao.gao@intel.com>, Xu Yilun <yilun.xu@intel.com>,
Li Xiaoyao <xiaoyao.li@intel.com>
Subject: Re: [PATCH v3 4/7] memory-attribute-manager: Introduce MemoryAttributeManager to manage RAMBLock with guest_memfd
Date: Mon, 24 Mar 2025 12:04:34 +0800 [thread overview]
Message-ID: <f804a892-482b-4eae-a21e-413e147e03da@intel.com> (raw)
In-Reply-To: <c94c26c5-9687-48df-9d40-0bca0892e625@intel.com>
On 3/20/2025 11:15 AM, Chenyi Qiang wrote:
>
>
> On 3/19/2025 7:56 PM, Gupta, Pankaj wrote:
>> On 3/19/2025 12:23 PM, Chenyi Qiang wrote:
>>>
>>>
>>> On 3/19/2025 4:55 PM, Gupta, Pankaj wrote:
>>>>
>>>>>>>>>> As the commit 852f0048f3 ("RAMBlock: make guest_memfd require
>>>>>>>>>> uncoordinated discard") highlighted, some subsystems like VFIO may
>>>>>>>>>> disable ram block discard. However, guest_memfd relies on the
>>>>>>>>>> discard
>>>>>>>>>> operation to perform page conversion between private and shared
>>>>>>>>>> memory.
>>>>>>>>>> This can lead to stale IOMMU mapping issue when assigning a
>>>>>>>>>> hardware
>>>>>>>>>> device to a confidential VM via shared memory. To address this,
>>>>>>>>>> it is
>>>>>>>>>> crucial to ensure systems like VFIO refresh its IOMMU mappings.
>>>>>>>>>>
>>>>>>>>>> RamDiscardManager is an existing concept (used by virtio-mem) to
>>>>>>>>>> adjust
>>>>>>>>>> VFIO mappings in relation to VM page assignment. Effectively page
>>>>>>>>>> conversion is similar to hot-removing a page in one mode and
>>>>>>>>>> adding it
>>>>>>>>>> back in the other. Therefore, similar actions are required for
>>>>>>>>>> page
>>>>>>>>>> conversion events. Introduce the RamDiscardManager to
>>>>>>>>>> guest_memfd to
>>>>>>>>>> facilitate this process.
>>>>>>>>>>
>>>>>>>>>> Since guest_memfd is not an object, it cannot directly
>>>>>>>>>> implement the
>>>>>>>>>> RamDiscardManager interface. One potential attempt is to implement
>>>>>>>>>> it in
>>>>>>>>>> HostMemoryBackend. This is not appropriate because guest_memfd is
>>>>>>>>>> per
>>>>>>>>>> RAMBlock. Some RAMBlocks have a memory backend but others do
>>>>>>>>>> not. In
>>>>>>>>>> particular, the ones like virtual BIOS calling
>>>>>>>>>> memory_region_init_ram_guest_memfd() do not.
>>>>>>>>>>
>>>>>>>>>> To manage the RAMBlocks with guest_memfd, define a new object
>>>>>>>>>> named
>>>>>>>>>> MemoryAttributeManager to implement the RamDiscardManager
>>>>>>>>>> interface. The
>>>>>>>>>
>>>>>>>>> Isn't this should be the other way around. 'MemoryAttributeManager'
>>>>>>>>> should be an interface and RamDiscardManager a type of it, an
>>>>>>>>> implementation?
>>>>>>>>
>>>>>>>> We want to use 'MemoryAttributeManager' to represent RAMBlock to
>>>>>>>> implement the RamDiscardManager interface callbacks because
>>>>>>>> RAMBlock is
>>>>>>>> not an object. It includes some metadata of guest_memfd like
>>>>>>>> shared_bitmap at the same time.
>>>>>>>>
>>>>>>>> I can't get it that make 'MemoryAttributeManager' an interface and
>>>>>>>> RamDiscardManager a type of it. Can you elaborate it a little bit? I
>>>>>>>> think at least we need someone to implement the RamDiscardManager
>>>>>>>> interface.
>>>>>>>
>>>>>>> shared <-> private is translated (abstracted) to "populated <->
>>>>>>> discarded", which makes sense. The other way around would be wrong.
>>>>>>>
>>>>>>> It's going to be interesting once we have more logical states, for
>>>>>>> example supporting virtio-mem for confidential VMs.
>>>>>>>
>>>>>>> Then we'd have "shared+populated, private+populated, shared+discard,
>>>>>>> private+discarded". Not sure if this could simply be achieved by
>>>>>>> allowing multiple RamDiscardManager that are effectively chained, or
>>>>>>> if we'd want a different interface.
>>>>>>
>>>>>> Exactly! In any case generic manager (parent class) would make more
>>>>>> sense that can work on different operations/states implemented in
>>>>>> child
>>>>>> classes (can be chained as well).
>>>>>
>>>>> Ah, we are talking about the generic state management. Sorry for my
>>>>> slow
>>>>> reaction.
>>>>>
>>>>> So we need to
>>>>> 1. Define a generic manager Interface, e.g.
>>>>> MemoryStateManager/GenericStateManager.
>>>>> 2. Make RamDiscardManager the child of MemoryStateManager which manages
>>>>> the state of populated and discarded.
>>>>> 3. Define a new child manager Interface PrivateSharedManager which
>>>>> manages the state of private and shared.
>>>>> 4. Define a new object ConfidentialMemoryAttribute to implement the
>>>>> PrivateSharedManager interface.
>>>>> (Welcome to rename the above Interface/Object)
>>>>>
>>>>> Is my understanding correct?
>>>>
>>>> Yes, in that direction. Where 'RamDiscardManager' &
>>>> 'PrivateSharedManager' are both child of 'GenericStateManager'.
>>>>
>>>> Depending on listeners registered, corresponding handlers can be called.
>>>
>>> Yes, it would be more generic and future extensive.
>>>
>>> Do we need to add this framework change directly? Or keep the current
>>> structure (abstract private/shared as discard/populated) and add the
>>> generic manager until the real case like virtio-mem for confidential VMs.
>>>
>>
>> Yes, maybe to start with we should add new (discard/populated) changes
>> with the new framework.
>>
>> In future the current framework can be extended for in-place conversion
>> for private-shared conversion (if require userspace help) and virtio-mem
>> like interfaces. Important is to have proper hierarchy with base bits
>> there.
>
> Thanks. Then I will follow this direction.
>
> To abstract the common parent class, what I can think of is to abstract
> it to manage a pair of opposite states (state set and state clear, like
> populate and discard) and define some similar common callbacks like
> notify_set() and notify_clear(), as long as we don't use it to manage
> more than two states in the future. Otherwise I may define a stub parent
> class.
Hi Pankaj & David,
How about defining them like:
---
For class definition: extract all the callbacks into parent class:
typedef int (*ReplayStateChange)(MemoryRegionSection *section, void
*opaque);
struct GenericStateManagerClass {
InterfaceClass parent_class;
uint64_t (*get_min_granularity)(const GenericStateManager *gsm,
const MemoryRegion *mr);
bool (*is_state_set)(const GenericStateManager *gsm,
const MemoryRegionSection *section);
int (*replay_state_set)(const GenericStateManager *gsm,
MemoryRegionSection *section,
ReplayStateChange replay_fn, void *opaque);
int (*replay_state_clear)(const GenericStateManager *gsm,
MemoryRegionSection *section,
ReplayStateChange replay_fn, void *opaque);
void (*register_listener)(GenericStateManager *gsm,
void* listener,
MemoryRegionSection *section);
void (*unregister_listener)(GenericStateManager *gsm,
void *listener);
}
struct RamDiscardManagerClass {
/* private */
GenericStateManagerClass parent_class;
};
struct PrivateSharedManagerClass {
/* private */
GenericStateManagerClass parent_class;
}
---
For listeners, embed the generic listener into specific listeners:
typedef int (*NotifyStateSet)(void *listener, MemoryRegionSection *section);
typedef int (*NotifyStateClear)(void *listener, MemoryRegionSection
*section);
struct StateChangeListener {
NotifyStateSet notify_state_set;
NotifyStateClear notify_state_clear;
MemoryRegionSection *section;
}
struct RamDiscardListener {
struct StateChangeListener scl;
bool double_discard_supported;
QLIST_ENTRY(RamDiscardListener) next;
};
struct PrivateSharedListener {
struct StateChangeListener scl;
QLIST_ENTRY(PrivateSharedListener) next;
}
---
For helpers,
- define the generic helpers:
void generic_state_manager_register_listener(GenericStateManager *gsm,
void *listener,
MemoryRegionSection *s)
{
GenericStateManagerClass gsmc = GENERATE_STATE_MANAGER_GET_CLASS(rdm);
g_assert(gsmc->register_listener);
gsmc->register_listener(gsm, listener, s);
}
- Keep RamDiscardManager specific helpers for compatibility if necessary:
void ram_discard_manager_register_listener(RamDiscardManager *rdm,
RamDiscardListener *rdl,
MemoryRegionSection *section)
{
GenericStateManagerClass gsmc = GENERATE_STATE_MANAGER_GET_CLASS(rdm);
GenericStateManager *gsm = GENERIC_STATE_MANAGER(rdm);
g_assert(gsmc->register_listener);
gsmc->register_listener(gsm, (void*)rdl, section);
}
>
>>
>> Thanks,
>> Pankaj
>
next prev parent reply other threads:[~2025-03-24 4:05 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-10 8:18 [PATCH v3 0/7] Enable shared device assignment Chenyi Qiang
2025-03-10 8:18 ` [PATCH v3 1/7] memory: Export a helper to get intersection of a MemoryRegionSection with a given range Chenyi Qiang
2025-03-10 8:18 ` [PATCH v3 2/7] memory: Change memory_region_set_ram_discard_manager() to return the result Chenyi Qiang
2025-03-10 8:18 ` [PATCH v3 3/7] memory: Unify the definiton of ReplayRamPopulate() and ReplayRamDiscard() Chenyi Qiang
2025-03-17 3:00 ` Kishen Maloor
2025-03-17 4:11 ` Chenyi Qiang
2025-03-10 8:18 ` [PATCH v3 4/7] memory-attribute-manager: Introduce MemoryAttributeManager to manage RAMBLock with guest_memfd Chenyi Qiang
2025-03-14 12:11 ` Gupta, Pankaj
2025-03-17 2:54 ` Chenyi Qiang
2025-03-17 10:36 ` David Hildenbrand
2025-03-17 17:01 ` Gupta, Pankaj
2025-03-18 1:54 ` Chenyi Qiang
2025-03-19 8:55 ` Gupta, Pankaj
2025-03-19 11:23 ` Chenyi Qiang
2025-03-19 11:56 ` Gupta, Pankaj
2025-03-20 3:15 ` Chenyi Qiang
2025-03-24 4:04 ` Chenyi Qiang [this message]
2025-03-10 8:18 ` [PATCH v3 5/7] memory-attribute-manager: Introduce a callback to notify the shared/private state change Chenyi Qiang
2025-03-10 8:18 ` [PATCH v3 6/7] memory: Attach MemoryAttributeManager to guest_memfd-backed RAMBlocks Chenyi Qiang
2025-03-14 8:21 ` Chenyi Qiang
2025-03-14 9:00 ` David Hildenbrand
2025-03-14 9:30 ` Chenyi Qiang
2025-03-14 9:50 ` David Hildenbrand
2025-03-14 10:23 ` Chenyi Qiang
2025-03-31 8:55 ` Chenyi Qiang
2025-03-17 6:18 ` Tony Lindgren
2025-03-17 7:32 ` Chenyi Qiang
2025-03-17 9:45 ` Tony Lindgren
2025-03-17 10:21 ` Chenyi Qiang
2025-03-17 11:07 ` Tony Lindgren
2025-03-10 8:18 ` [PATCH v3 7/7] RAMBlock: Make guest_memfd require coordinate discard Chenyi Qiang
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=f804a892-482b-4eae-a21e-413e147e03da@intel.com \
--to=chenyi.qiang@intel.com \
--cc=aik@amd.com \
--cc=chao.gao@intel.com \
--cc=chao.p.peng@intel.com \
--cc=dan.j.williams@intel.com \
--cc=david@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pankaj.gupta@amd.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=xiaoyao.li@intel.com \
--cc=yilun.xu@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox