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
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
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
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
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 >
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
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
© 2016 - 2026 Red Hat, Inc.