[PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove

Pratik R. Sampat posted 2 patches 3 weeks, 6 days ago
There is a newer version of this series
[PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Pratik R. Sampat 3 weeks, 6 days ago
Transition memory to the shared state during a hot-remove operation so
that it can be re-used by the hypervisor. This also applies when memory
is intended to be hotplugged back in later, as those pages will need to
be re-accepted after crossing the trust boundary.

Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
 arch/x86/coco/sev/core.c                 | 13 +++++++++++++
 arch/x86/include/asm/sev.h               |  2 ++
 arch/x86/include/asm/unaccepted_memory.h |  9 +++++++++
 mm/memory_hotplug.c                      |  3 +++
 4 files changed, 27 insertions(+)

diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 9ae3b11754e6..63d8f44b76eb 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -703,6 +703,19 @@ void snp_accept_memory(phys_addr_t start, phys_addr_t end)
 	set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
 }
 
+void snp_unaccept_memory(phys_addr_t start, phys_addr_t end)
+{
+	unsigned long vaddr, npages;
+
+	if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+		return;
+
+	vaddr = (unsigned long)__va(start);
+	npages = (end - start) >> PAGE_SHIFT;
+
+	set_pages_state(vaddr, npages, SNP_PAGE_STATE_SHARED);
+}
+
 static int vmgexit_ap_control(u64 event, struct sev_es_save_area *vmsa, u32 apic_id)
 {
 	bool create = event != SVM_VMGEXIT_AP_DESTROY;
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 0e6c0940100f..3327de663793 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -514,6 +514,7 @@ bool snp_init(struct boot_params *bp);
 void snp_dmi_setup(void);
 int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input);
 void snp_accept_memory(phys_addr_t start, phys_addr_t end);
+void snp_unaccept_memory(phys_addr_t start, phys_addr_t end);
 u64 snp_get_unsupported_features(u64 status);
 u64 sev_get_status(void);
 void sev_show_status(void);
@@ -623,6 +624,7 @@ static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call,
 	return -ENOTTY;
 }
 static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
+static inline void snp_unaccept_memory(phys_addr_t start, phys_addr_t end) { }
 static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
 static inline u64 sev_get_status(void) { return 0; }
 static inline void sev_show_status(void) { }
diff --git a/arch/x86/include/asm/unaccepted_memory.h b/arch/x86/include/asm/unaccepted_memory.h
index f5937e9866ac..8715be843e65 100644
--- a/arch/x86/include/asm/unaccepted_memory.h
+++ b/arch/x86/include/asm/unaccepted_memory.h
@@ -18,6 +18,15 @@ static inline void arch_accept_memory(phys_addr_t start, phys_addr_t end)
 	}
 }
 
+static inline void arch_unaccept_memory(phys_addr_t start, phys_addr_t end)
+{
+	if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
+		snp_unaccept_memory(start, end);
+	} else {
+		panic("Cannot unaccept memory: unknown platform\n");
+	}
+}
+
 static inline struct efi_unaccepted_memory *efi_get_unaccepted_table(void)
 {
 	if (efi.unaccepted == EFI_INVALID_TABLE_ADDR)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 8cfbf0541430..718f729cf687 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -2242,6 +2242,9 @@ static int try_remove_memory(u64 start, u64 size)
 
 	mem_hotplug_begin();
 
+	if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY))
+		arch_unaccept_memory(start, start + size);
+
 	rc = memory_blocks_have_altmaps(start, size);
 	if (rc < 0) {
 		mem_hotplug_done();
-- 
2.52.0
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Kiryl Shutsemau 3 weeks, 5 days ago
On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
> Transition memory to the shared state during a hot-remove operation so
> that it can be re-used by the hypervisor. This also applies when memory
> is intended to be hotplugged back in later, as those pages will need to
> be re-accepted after crossing the trust boundary.

Hm. What happens when we hot-remove memory that was there at the boot
and there's bitmap space for it?

Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
the memory from under guest at any time without a warning. Coverting
memory to shared shouldn't make a difference as along as re-adding the
same GPA range triggers accept.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Pratik R. Sampat 3 weeks, 5 days ago

On 1/13/2026 4:28 AM, Kiryl Shutsemau wrote:
> On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
>> Transition memory to the shared state during a hot-remove operation so
>> that it can be re-used by the hypervisor. This also applies when memory
>> is intended to be hotplugged back in later, as those pages will need to
>> be re-accepted after crossing the trust boundary.
> 
> Hm. What happens when we hot-remove memory that was there at the boot
> and there's bitmap space for it?
> 

While hotplug ranges gotten from SRAT don't seem to overlap with the
conventional ranges in the unaccepted table, EFI_MEMORY_HOT_PLUGGABLE
attribute could indicate boot time memory that could be hot-removed. I
could potentially unset the bitmap first, if the bit exists and then
unaccept.

Similarly, I could also check if the bitmap is large enough to set the
bit before I call arch_accept_memory() (This may not really be needed 
though).

> Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
> the memory from under guest at any time without a warning. Coverting
> memory to shared shouldn't make a difference as along as re-adding the
> same GPA range triggers accept.
> 

That makes sense. The only scenario where we could run into trouble on
SNP platforms is when we redo a qemu device_add after a device_del
without first removing the memory object entirely since same-state
transitions result in guest termination.

This means we must always follow a device_del with an object_del on
removal. Otherwise, the onus would then be on the VMM to transition
the memory back to shared before re-adding it to the guest.

However, if this flow is not a concern to begin with then I could
probably just drop this patch?

--Pratik
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Kiryl Shutsemau 3 weeks, 5 days ago
On Tue, Jan 13, 2026 at 11:10:21AM -0600, Pratik R. Sampat wrote:
> 
> 
> On 1/13/2026 4:28 AM, Kiryl Shutsemau wrote:
> > On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
> > > Transition memory to the shared state during a hot-remove operation so
> > > that it can be re-used by the hypervisor. This also applies when memory
> > > is intended to be hotplugged back in later, as those pages will need to
> > > be re-accepted after crossing the trust boundary.
> > 
> > Hm. What happens when we hot-remove memory that was there at the boot
> > and there's bitmap space for it?
> > 
> 
> While hotplug ranges gotten from SRAT don't seem to overlap with the
> conventional ranges in the unaccepted table, EFI_MEMORY_HOT_PLUGGABLE
> attribute could indicate boot time memory that could be hot-removed. I
> could potentially unset the bitmap first, if the bit exists and then
> unaccept.
> 
> Similarly, I could also check if the bitmap is large enough to set the
> bit before I call arch_accept_memory() (This may not really be needed
> though).
> 
> > Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
> > the memory from under guest at any time without a warning. Coverting
> > memory to shared shouldn't make a difference as along as re-adding the
> > same GPA range triggers accept.
> > 
> 
> That makes sense. The only scenario where we could run into trouble on
> SNP platforms is when we redo a qemu device_add after a device_del
> without first removing the memory object entirely since same-state
> transitions result in guest termination.
> 
> This means we must always follow a device_del with an object_del on
> removal. Otherwise, the onus would then be on the VMM to transition
> the memory back to shared before re-adding it to the guest.

This seems to be one-of-many possible ways of VMM to get guest terminated.
DoS is not in something confidential computing aims to prevent.

> However, if this flow is not a concern to begin with then I could
> probably just drop this patch?

Yes, please.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Pratik R. Sampat 3 weeks, 5 days ago

On 1/13/26 11:53 AM, Kiryl Shutsemau wrote:
> On Tue, Jan 13, 2026 at 11:10:21AM -0600, Pratik R. Sampat wrote:
>>
>>
>> On 1/13/2026 4:28 AM, Kiryl Shutsemau wrote:
>>> On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
>>>> Transition memory to the shared state during a hot-remove operation so
>>>> that it can be re-used by the hypervisor. This also applies when memory
>>>> is intended to be hotplugged back in later, as those pages will need to
>>>> be re-accepted after crossing the trust boundary.
>>>
>>> Hm. What happens when we hot-remove memory that was there at the boot
>>> and there's bitmap space for it?
>>>
>>
>> While hotplug ranges gotten from SRAT don't seem to overlap with the
>> conventional ranges in the unaccepted table, EFI_MEMORY_HOT_PLUGGABLE
>> attribute could indicate boot time memory that could be hot-removed. I
>> could potentially unset the bitmap first, if the bit exists and then
>> unaccept.
>>
>> Similarly, I could also check if the bitmap is large enough to set the
>> bit before I call arch_accept_memory() (This may not really be needed
>> though).
>>
>>> Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
>>> the memory from under guest at any time without a warning. Coverting
>>> memory to shared shouldn't make a difference as along as re-adding the
>>> same GPA range triggers accept.
>>>
>>
>> That makes sense. The only scenario where we could run into trouble on
>> SNP platforms is when we redo a qemu device_add after a device_del
>> without first removing the memory object entirely since same-state
>> transitions result in guest termination.
>>
>> This means we must always follow a device_del with an object_del on
>> removal. Otherwise, the onus would then be on the VMM to transition
>> the memory back to shared before re-adding it to the guest.
> 
> This seems to be one-of-many possible ways of VMM to get guest terminated.
> DoS is not in something confidential computing aims to prevent.
> 
>> However, if this flow is not a concern to begin with then I could
>> probably just drop this patch?
> 
> Yes, please.

Putting more thought into it, memory unacceptance on remove may be required
after all at least for SNP platforms.

Consider a scenario:
* Guest accepts a GPA say G1, mapped to a host physical address H1.
* We attempt to hot-remove the memory. If the guest does not unaccept the memory
  now then G1 to H1 mapping within the RMP will still exist.
* Then if the hypervisor later hot-adds the memory to G1, it will be now mapped
  to H3 and this new mapping will be accepted.

This will essentially mean that we have 2 RMP entries: One for H1 and another
for H3 mapped for G1 which are both validated / accepted which can then be
swapped at will and compromise integrity.

--Pratik
>
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Kiryl Shutsemau 3 weeks, 4 days ago
On Tue, Jan 13, 2026 at 12:22:33PM -0600, Pratik R. Sampat wrote:
> 
> 
> On 1/13/26 11:53 AM, Kiryl Shutsemau wrote:
> > On Tue, Jan 13, 2026 at 11:10:21AM -0600, Pratik R. Sampat wrote:
> >>
> >>
> >> On 1/13/2026 4:28 AM, Kiryl Shutsemau wrote:
> >>> On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
> >>>> Transition memory to the shared state during a hot-remove operation so
> >>>> that it can be re-used by the hypervisor. This also applies when memory
> >>>> is intended to be hotplugged back in later, as those pages will need to
> >>>> be re-accepted after crossing the trust boundary.
> >>>
> >>> Hm. What happens when we hot-remove memory that was there at the boot
> >>> and there's bitmap space for it?
> >>>
> >>
> >> While hotplug ranges gotten from SRAT don't seem to overlap with the
> >> conventional ranges in the unaccepted table, EFI_MEMORY_HOT_PLUGGABLE
> >> attribute could indicate boot time memory that could be hot-removed. I
> >> could potentially unset the bitmap first, if the bit exists and then
> >> unaccept.
> >>
> >> Similarly, I could also check if the bitmap is large enough to set the
> >> bit before I call arch_accept_memory() (This may not really be needed
> >> though).
> >>
> >>> Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
> >>> the memory from under guest at any time without a warning. Coverting
> >>> memory to shared shouldn't make a difference as along as re-adding the
> >>> same GPA range triggers accept.
> >>>
> >>
> >> That makes sense. The only scenario where we could run into trouble on
> >> SNP platforms is when we redo a qemu device_add after a device_del
> >> without first removing the memory object entirely since same-state
> >> transitions result in guest termination.
> >>
> >> This means we must always follow a device_del with an object_del on
> >> removal. Otherwise, the onus would then be on the VMM to transition
> >> the memory back to shared before re-adding it to the guest.
> > 
> > This seems to be one-of-many possible ways of VMM to get guest terminated.
> > DoS is not in something confidential computing aims to prevent.
> > 
> >> However, if this flow is not a concern to begin with then I could
> >> probably just drop this patch?
> > 
> > Yes, please.
> 
> Putting more thought into it, memory unacceptance on remove may be required
> after all at least for SNP platforms.
> 
> Consider a scenario:
> * Guest accepts a GPA say G1, mapped to a host physical address H1.
> * We attempt to hot-remove the memory. If the guest does not unaccept the memory
>   now then G1 to H1 mapping within the RMP will still exist.
> * Then if the hypervisor later hot-adds the memory to G1, it will be now mapped
>   to H3 and this new mapping will be accepted.
> 
> This will essentially mean that we have 2 RMP entries: One for H1 and another
> for H3 mapped for G1 which are both validated / accepted which can then be
> swapped at will and compromise integrity.

I don't know much about SEV, but I assume RMP is similar to PAMT in TDX
where TDX module maintains metadata for host physical memory.

What side problems do you for guest here?

I probably miss something, but it seems to be VMM problem, no? I mean if
VMM doesn't update RMP on replacing one HPA to another for the GPA, it
is bug in VMM housekeeping. Guest is not responsible for this.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v2 2/2] mm/memory_hotplug: Add support to unaccept memory after hot-remove
Posted by Pratik R. Sampat 3 weeks, 4 days ago

On 1/14/26 4:47 AM, Kiryl Shutsemau wrote:
> On Tue, Jan 13, 2026 at 12:22:33PM -0600, Pratik R. Sampat wrote:
>>
>>
>> On 1/13/26 11:53 AM, Kiryl Shutsemau wrote:
>>> On Tue, Jan 13, 2026 at 11:10:21AM -0600, Pratik R. Sampat wrote:
>>>>
>>>>
>>>> On 1/13/2026 4:28 AM, Kiryl Shutsemau wrote:
>>>>> On Mon, Jan 12, 2026 at 02:23:00PM -0600, Pratik R. Sampat wrote:
>>>>>> Transition memory to the shared state during a hot-remove operation so
>>>>>> that it can be re-used by the hypervisor. This also applies when memory
>>>>>> is intended to be hotplugged back in later, as those pages will need to
>>>>>> be re-accepted after crossing the trust boundary.
>>>>>
>>>>> Hm. What happens when we hot-remove memory that was there at the boot
>>>>> and there's bitmap space for it?
>>>>>
>>>>
>>>> While hotplug ranges gotten from SRAT don't seem to overlap with the
>>>> conventional ranges in the unaccepted table, EFI_MEMORY_HOT_PLUGGABLE
>>>> attribute could indicate boot time memory that could be hot-removed. I
>>>> could potentially unset the bitmap first, if the bit exists and then
>>>> unaccept.
>>>>
>>>> Similarly, I could also check if the bitmap is large enough to set the
>>>> bit before I call arch_accept_memory() (This may not really be needed
>>>> though).
>>>>
>>>>> Also, I'm not sure why it is needed. At least in TDX case, VMM can pull
>>>>> the memory from under guest at any time without a warning. Coverting
>>>>> memory to shared shouldn't make a difference as along as re-adding the
>>>>> same GPA range triggers accept.
>>>>>
>>>>
>>>> That makes sense. The only scenario where we could run into trouble on
>>>> SNP platforms is when we redo a qemu device_add after a device_del
>>>> without first removing the memory object entirely since same-state
>>>> transitions result in guest termination.
>>>>
>>>> This means we must always follow a device_del with an object_del on
>>>> removal. Otherwise, the onus would then be on the VMM to transition
>>>> the memory back to shared before re-adding it to the guest.
>>>
>>> This seems to be one-of-many possible ways of VMM to get guest terminated.
>>> DoS is not in something confidential computing aims to prevent.
>>>
>>>> However, if this flow is not a concern to begin with then I could
>>>> probably just drop this patch?
>>>
>>> Yes, please.
>>
>> Putting more thought into it, memory unacceptance on remove may be required
>> after all at least for SNP platforms.
>>
>> Consider a scenario:
>> * Guest accepts a GPA say G1, mapped to a host physical address H1.
>> * We attempt to hot-remove the memory. If the guest does not unaccept the memory
>>   now then G1 to H1 mapping within the RMP will still exist.
>> * Then if the hypervisor later hot-adds the memory to G1, it will be now mapped
>>   to H3 and this new mapping will be accepted.
>>
>> This will essentially mean that we have 2 RMP entries: One for H1 and another
>> for H3 mapped for G1 which are both validated / accepted which can then be
>> swapped at will and compromise integrity.
> 
> I don't know much about SEV, but I assume RMP is similar to PAMT in TDX
> where TDX module maintains metadata for host physical memory.
> 
> What side problems do you for guest here?
> 
> I probably miss something, but it seems to be VMM problem, no? I mean if
> VMM doesn't update RMP on replacing one HPA to another for the GPA, it
> is bug in VMM housekeeping. Guest is not responsible for this.
> 

Right, the problem is that we do not inherently trust the host to make change.
That is why in my understanding, the guest is responsible for validating and
rescinding those pages.

--Pratik