Skip to content

Commit 0b210fa

Browse files
committed
KVM: x86/mmu: Add "never" option to allow sticky disabling of nx_huge_pages
Add a "never" option to the nx_huge_pages module param to allow userspace to do a one-way hard disabling of the mitigation, and don't create the per-VM recovery threads when the mitigation is hard disabled. Letting userspace pinky swear that userspace doesn't want to enable NX mitigation (without reloading KVM) allows certain use cases to avoid the latency problems associated with spawning a kthread for each VM. E.g. in FaaS use cases, the guest kernel is trusted and the host may create 100+ VMs per logical CPU, which can result in 100ms+ latencies when a burst of VMs is created. Reported-by: Li RongQing <lirongqing@baidu.com> Closes: https://lore.kernel.org/all/1679555884-32544-1-git-send-email-lirongqing@baidu.com Cc: Yong He <zhuangel570@gmail.com> Cc: Robert Hoo <robert.hoo.linux@gmail.com> Cc: Kai Huang <kai.huang@intel.com> Reviewed-by: Robert Hoo <robert.hoo.linux@gmail.com> Acked-by: Kai Huang <kai.huang@intel.com> Tested-by: Luiz Capitulino <luizcap@amazon.com> Reviewed-by: Li RongQing <lirongqing@baidu.com> Link: https://lore.kernel.org/r/20230602005859.784190-1-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 762b33e commit 0b210fa

1 file changed

Lines changed: 36 additions & 5 deletions

File tree

arch/x86/kvm/mmu/mmu.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858

5959
extern bool itlb_multihit_kvm_mitigation;
6060

61+
static bool nx_hugepage_mitigation_hard_disabled;
62+
6163
int __read_mostly nx_huge_pages = -1;
6264
static uint __read_mostly nx_huge_pages_recovery_period_ms;
6365
#ifdef CONFIG_PREEMPT_RT
@@ -67,12 +69,13 @@ static uint __read_mostly nx_huge_pages_recovery_ratio = 0;
6769
static uint __read_mostly nx_huge_pages_recovery_ratio = 60;
6870
#endif
6971

72+
static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp);
7073
static int set_nx_huge_pages(const char *val, const struct kernel_param *kp);
7174
static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel_param *kp);
7275

7376
static const struct kernel_param_ops nx_huge_pages_ops = {
7477
.set = set_nx_huge_pages,
75-
.get = param_get_bool,
78+
.get = get_nx_huge_pages,
7679
};
7780

7881
static const struct kernel_param_ops nx_huge_pages_recovery_param_ops = {
@@ -6852,6 +6855,14 @@ static void mmu_destroy_caches(void)
68526855
kmem_cache_destroy(mmu_page_header_cache);
68536856
}
68546857

6858+
static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp)
6859+
{
6860+
if (nx_hugepage_mitigation_hard_disabled)
6861+
return sprintf(buffer, "never\n");
6862+
6863+
return param_get_bool(buffer, kp);
6864+
}
6865+
68556866
static bool get_nx_auto_mode(void)
68566867
{
68576868
/* Return true when CPU has the bug, and mitigations are ON */
@@ -6868,15 +6879,29 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp)
68686879
bool old_val = nx_huge_pages;
68696880
bool new_val;
68706881

6882+
if (nx_hugepage_mitigation_hard_disabled)
6883+
return -EPERM;
6884+
68716885
/* In "auto" mode deploy workaround only if CPU has the bug. */
6872-
if (sysfs_streq(val, "off"))
6886+
if (sysfs_streq(val, "off")) {
68736887
new_val = 0;
6874-
else if (sysfs_streq(val, "force"))
6888+
} else if (sysfs_streq(val, "force")) {
68756889
new_val = 1;
6876-
else if (sysfs_streq(val, "auto"))
6890+
} else if (sysfs_streq(val, "auto")) {
68776891
new_val = get_nx_auto_mode();
6878-
else if (kstrtobool(val, &new_val) < 0)
6892+
} else if (sysfs_streq(val, "never")) {
6893+
new_val = 0;
6894+
6895+
mutex_lock(&kvm_lock);
6896+
if (!list_empty(&vm_list)) {
6897+
mutex_unlock(&kvm_lock);
6898+
return -EBUSY;
6899+
}
6900+
nx_hugepage_mitigation_hard_disabled = true;
6901+
mutex_unlock(&kvm_lock);
6902+
} else if (kstrtobool(val, &new_val) < 0) {
68796903
return -EINVAL;
6904+
}
68806905

68816906
__set_nx_huge_pages(new_val);
68826907

@@ -7014,6 +7039,9 @@ static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel
70147039
uint old_period, new_period;
70157040
int err;
70167041

7042+
if (nx_hugepage_mitigation_hard_disabled)
7043+
return -EPERM;
7044+
70177045
was_recovery_enabled = calc_nx_huge_pages_recovery_period(&old_period);
70187046

70197047
err = param_set_uint(val, kp);
@@ -7169,6 +7197,9 @@ int kvm_mmu_post_init_vm(struct kvm *kvm)
71697197
{
71707198
int err;
71717199

7200+
if (nx_hugepage_mitigation_hard_disabled)
7201+
return 0;
7202+
71727203
err = kvm_vm_create_worker_thread(kvm, kvm_nx_huge_page_recovery_worker, 0,
71737204
"kvm-nx-lpage-recovery",
71747205
&kvm->arch.nx_huge_page_recovery_thread);

0 commit comments

Comments
 (0)