From: Ashish Kalra RMPOPT table is a per-processor table which indicates if 1GB regions of physical memory are entirely hypervisor-owned or not. When performing host memory accesses in hypervisor mode as well as non-SNP guest mode, the processor may consult the RMPOPT table to potentially skip an RMP access and improve performance. Events such as RMPUPDATE or SNP_INIT can clear RMP optimizations. Add an interface to re-enable those optimizations. Signed-off-by: Ashish Kalra --- arch/x86/include/asm/sev.h | 2 ++ arch/x86/virt/svm/sev.c | 17 +++++++++++++++++ drivers/crypto/ccp/sev-dev.c | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 0e6c0940100f..451fb2b2a0f7 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -657,6 +657,7 @@ int rmp_make_shared(u64 pfn, enum pg_level level); void __snp_leak_pages(u64 pfn, unsigned int npages, bool dump_rmp); void kdump_sev_callback(void); void snp_fixup_e820_tables(void); +int snp_perform_rmp_optimization(void); static inline void snp_leak_pages(u64 pfn, unsigned int pages) { __snp_leak_pages(pfn, pages, true); @@ -677,6 +678,7 @@ static inline void __snp_leak_pages(u64 pfn, unsigned int npages, bool dump_rmp) static inline void snp_leak_pages(u64 pfn, unsigned int npages) {} static inline void kdump_sev_callback(void) { } static inline void snp_fixup_e820_tables(void) {} +static inline int snp_perform_rmp_optimization(void) { return 0; } #endif #endif diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index a0d38fc50698..713afcc2fab3 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -1305,6 +1305,23 @@ int rmp_make_shared(u64 pfn, enum pg_level level) } EXPORT_SYMBOL_GPL(rmp_make_shared); +int snp_perform_rmp_optimization(void) +{ + if (!cpu_feature_enabled(X86_FEATURE_RMPOPT)) + return -EINVAL; + + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) + return -EINVAL; + + if (!(rmp_cfg & MSR_AMD64_SEG_RMP_ENABLED)) + return -EINVAL; + + rmpopt_all_physmem(); + + return 0; +} +EXPORT_SYMBOL_GPL(snp_perform_rmp_optimization); + void __snp_leak_pages(u64 pfn, unsigned int npages, bool dump_rmp) { struct page *page = pfn_to_page(pfn); diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 1cdadddb744e..d3df29b0c6bf 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1478,6 +1478,10 @@ static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid) } snp_hv_fixed_pages_state_update(sev, HV_FIXED); + + /* SNP_INIT clears the RMPOPT table, re-enable RMP optimizations */ + snp_perform_rmp_optimization(); + sev->snp_initialized = true; dev_dbg(sev->dev, "SEV-SNP firmware initialized, SEV-TIO is %s\n", data.tio_en ? "enabled" : "disabled"); -- 2.43.0