From: Ashish Kalra Use configfs as an interface to re-enable RMP optimizations at runtime When SNP guests are launched, RMPUPDATE disables the corresponding RMPOPT optimizations. Therefore, an interface is required to manually re-enable RMP optimizations, as no mechanism currently exists to do so during SNP guest cleanup. Also select CONFIG_CONFIGFS_FS when host SEV or SNP support is enabled. Suggested-by: Thomas Lendacky Signed-off-by: Ashish Kalra --- arch/x86/kvm/Kconfig | 1 + arch/x86/virt/svm/sev.c | 79 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index d916bd766c94..8fb21893ec8c 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -164,6 +164,7 @@ config KVM_AMD_SEV select HAVE_KVM_ARCH_GMEM_PREPARE select HAVE_KVM_ARCH_GMEM_INVALIDATE select HAVE_KVM_ARCH_GMEM_POPULATE + select CONFIGFS_FS help Provides support for launching encrypted VMs which use Secure Encrypted Virtualization (SEV), Secure Encrypted Virtualization with diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index 713afcc2fab3..0f71a045e4aa 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -146,6 +147,10 @@ struct rmpopt_socket_config { int current_node_idx; }; +#define RMPOPT_CONFIGFS_NAME "rmpopt" + +static atomic_t rmpopt_in_progress = ATOMIC_INIT(0); + #undef pr_fmt #define pr_fmt(fmt) "SEV-SNP: " fmt @@ -581,6 +586,9 @@ static int rmpopt_kthread(void *__unused) cond_resched(); } + /* Clear in_progress flag before going to sleep */ + atomic_set(&rmpopt_in_progress, 0); + set_current_state(TASK_INTERRUPTIBLE); schedule(); } @@ -595,6 +603,75 @@ static void rmpopt_all_physmem(void) wake_up_process(rmpopt_task); } +static ssize_t rmpopt_action_show(struct config_item *item, char *page) +{ + return sprintf(page, "RMP optimization in progress: %s\n", + atomic_read(&rmpopt_in_progress) == 1 ? "Yes" : "No"); +} + +static ssize_t rmpopt_action_store(struct config_item *item, + const char *page, size_t count) +{ + int in_progress_flag, ret; + unsigned int action; + + ret = kstrtouint(page, 10, &action); + if (ret) + return ret; + + if (action == 1) { + /* perform RMP re-optimizations */ + in_progress_flag = atomic_cmpxchg(&rmpopt_in_progress, 0, 1); + if (!in_progress_flag) + rmpopt_all_physmem(); + } else { + return -EINVAL; + } + + return count; +} + +static ssize_t rmpopt_description_show(struct config_item *item, char *page) +{ + return sprintf(page, "[RMPOPT]\n\necho 1 > action to perform RMP optimization.\n"); +} + +CONFIGFS_ATTR(rmpopt_, action); +CONFIGFS_ATTR_RO(rmpopt_, description); + +static struct configfs_attribute *rmpopt_attrs[] = { + &rmpopt_attr_action, + &rmpopt_attr_description, + NULL, +}; + +static const struct config_item_type rmpopt_config_type = { + .ct_attrs = rmpopt_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem rmpopt_configfs = { + .su_group = { + .cg_item = { + .ci_namebuf = RMPOPT_CONFIGFS_NAME, + .ci_type = &rmpopt_config_type, + }, + }, + .su_mutex = __MUTEX_INITIALIZER(rmpopt_configfs.su_mutex), +}; + +static int rmpopt_configfs_setup(void) +{ + int ret; + + config_group_init(&rmpopt_configfs.su_group); + ret = configfs_register_subsystem(&rmpopt_configfs); + if (ret) + pr_err("Error %d while registering subsystem %s\n", ret, RMPOPT_CONFIGFS_NAME); + + return ret; +} + static void __configure_rmpopt(void *val) { u64 rmpopt_base = ((u64)val & PUD_MASK) | MSR_AMD64_RMPOPT_ENABLE; @@ -770,6 +847,8 @@ static __init void configure_and_enable_rmpopt(void) */ rmpopt_all_physmem(); + rmpopt_configfs_setup(); + free_cpumask: free_cpumask_var(primary_threads_cpulist); } -- 2.43.0