Skip to content

Commit 8dac642

Browse files
ashkalrabp3tk0v
authored andcommitted
x86/sev: Introduce an SNP leaked pages list
Pages are unsafe to be released back to the page-allocator if they have been transitioned to firmware/guest state and can't be reclaimed or transitioned back to hypervisor/shared state. In this case, add them to an internal leaked pages list to ensure that they are not freed or touched/accessed to cause fatal page faults. [ mdr: Relocate to arch/x86/virt/svm/sev.c ] Suggested-by: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Ashish Kalra <ashish.kalra@amd.com> Signed-off-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Vlastimil Babka <vbabka@suse.cz> Link: https://lore.kernel.org/r/20240126041126.1927228-16-michael.roth@amd.com
1 parent 18085ac commit 8dac642

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

arch/x86/include/asm/sev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ void snp_dump_hva_rmpentry(unsigned long address);
264264
int psmash(u64 pfn);
265265
int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immutable);
266266
int rmp_make_shared(u64 pfn, enum pg_level level);
267+
void snp_leak_pages(u64 pfn, unsigned int npages);
267268
#else
268269
static inline bool snp_probe_rmptable_info(void) { return false; }
269270
static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -275,6 +276,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
275276
return -ENODEV;
276277
}
277278
static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
279+
static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
278280
#endif
279281

280282
#endif

arch/x86/virt/svm/sev.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ static u64 probed_rmp_base, probed_rmp_size;
6565
static struct rmpentry *rmptable __ro_after_init;
6666
static u64 rmptable_max_pfn __ro_after_init;
6767

68+
static LIST_HEAD(snp_leaked_pages_list);
69+
static DEFINE_SPINLOCK(snp_leaked_pages_list_lock);
70+
71+
static unsigned long snp_nr_leaked_pages;
72+
6873
#undef pr_fmt
6974
#define pr_fmt(fmt) "SEV-SNP: " fmt
7075

@@ -515,3 +520,35 @@ int rmp_make_shared(u64 pfn, enum pg_level level)
515520
return rmpupdate(pfn, &state);
516521
}
517522
EXPORT_SYMBOL_GPL(rmp_make_shared);
523+
524+
void snp_leak_pages(u64 pfn, unsigned int npages)
525+
{
526+
struct page *page = pfn_to_page(pfn);
527+
528+
pr_warn("Leaking PFN range 0x%llx-0x%llx\n", pfn, pfn + npages);
529+
530+
spin_lock(&snp_leaked_pages_list_lock);
531+
while (npages--) {
532+
533+
/*
534+
* Reuse the page's buddy list for chaining into the leaked
535+
* pages list. This page should not be on a free list currently
536+
* and is also unsafe to be added to a free list.
537+
*/
538+
if (likely(!PageCompound(page)) ||
539+
540+
/*
541+
* Skip inserting tail pages of compound page as
542+
* page->buddy_list of tail pages is not usable.
543+
*/
544+
(PageHead(page) && compound_nr(page) <= npages))
545+
list_add_tail(&page->buddy_list, &snp_leaked_pages_list);
546+
547+
dump_rmpentry(pfn);
548+
snp_nr_leaked_pages++;
549+
pfn++;
550+
page++;
551+
}
552+
spin_unlock(&snp_leaked_pages_list_lock);
553+
}
554+
EXPORT_SYMBOL_GPL(snp_leak_pages);

0 commit comments

Comments
 (0)