Messages in this thread Patch in this message | | | Date | Fri, 22 Jul 2022 16:02:38 -0700 | Subject | [PATCH 2/5] kvm/x86: add controls to enable/disable paravirtualized system calls | From | Andrei Vagin <> |
| |
The following change will add a new hypercall to execute host syscalls.
This hypercall is helpful for user-mode kernel solutions such as gVisor that needs to manage multiple address spaces.
The new hypercall is a backdoor for most KVM users, so it must be disabled by default. This change introduces a new capability that has to be set to enable the hypercall. There is another standard way to allow hypercalls by using KVM_SET_CPUID2. It isn't suitable in this case because one of the common ways of using it is to request all available features (KVM_GET_SUPPORTED_CPUID) and let them all together. In this case, it is a hard requirement that the new hypercall can be enabled only intentionally.
Signed-off-by: Andrei Vagin <avagin@google.com> --- arch/x86/include/uapi/asm/kvm_para.h | 3 +++ arch/x86/kvm/cpuid.c | 25 +++++++++++++++++++++++++ arch/x86/kvm/cpuid.h | 8 +++++++- arch/x86/kvm/x86.c | 4 ++++ include/uapi/linux/kvm.h | 1 + 5 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h index 6e64b27b2c1e..84ad13ffc23c 100644 --- a/arch/x86/include/uapi/asm/kvm_para.h +++ b/arch/x86/include/uapi/asm/kvm_para.h @@ -37,6 +37,9 @@ #define KVM_FEATURE_HC_MAP_GPA_RANGE 16 #define KVM_FEATURE_MIGRATION_CONTROL 17 +/* Features that are not controlled by KVM_SET_CPUID2. */ +#define KVM_FEATURE_PV_HOST_SYSCALL 31 + #define KVM_HINTS_REALTIME 0 /* The last 8 bits are used to indicate how to interpret the flags field diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index de6d44e07e34..4fdfe9409506 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -104,6 +104,10 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu, return -EINVAL; } + best = cpuid_entry2_find(entries, nent, KVM_CPUID_FEATURES, 0); + if (best && (best->eax & (1<<KVM_FEATURE_PV_HOST_SYSCALL))) + return -EINVAL; + /* * Exposing dynamic xfeatures to the guest requires additional * enabling in the FPU, e.g. to expand the guest XSAVE state size. @@ -273,6 +277,27 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e } } +int kvm_vcpu_pv_set_host_syscall(struct kvm_vcpu *vcpu, bool set) +{ + struct kvm_cpuid_entry2 *best; + + if (!vcpu->arch.pv_cpuid.enforce) + return -EINVAL; + + best = kvm_find_cpuid_entry(vcpu, KVM_CPUID_FEATURES, 0); + if (!best) + return -EINVAL; + + if (set) + best->eax |= 1 << KVM_FEATURE_PV_HOST_SYSCALL; + else + best->eax &= ~(1 << KVM_FEATURE_PV_HOST_SYSCALL); + + kvm_update_pv_runtime(vcpu); + + return 0; +} + void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) { __kvm_update_cpuid_runtime(vcpu, vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 8a770b481d9d..80721093b82b 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -219,10 +219,16 @@ static __always_inline void kvm_cpu_cap_check_and_set(unsigned int x86_feature) static __always_inline bool guest_pv_has(struct kvm_vcpu *vcpu, unsigned int kvm_feature) { - if (!vcpu->arch.pv_cpuid.enforce) + if (!vcpu->arch.pv_cpuid.enforce) { + if (kvm_feature == KVM_FEATURE_PV_HOST_SYSCALL) + return false; + return true; + } return vcpu->arch.pv_cpuid.features & (1u << kvm_feature); } +int kvm_vcpu_pv_set_host_syscall(struct kvm_vcpu *vcpu, bool set); + #endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e5fa335a4ea7..19e634768161 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5306,6 +5306,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, kvm_update_pv_runtime(vcpu); return 0; + + case KVM_CAP_PV_HOST_SYSCALL: + return kvm_vcpu_pv_set_host_syscall(vcpu, cap->args[0]); + default: return -EINVAL; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 860f867c50c0..89ed59d13877 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1157,6 +1157,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216 +#define KVM_CAP_PV_HOST_SYSCALL 217 #ifdef KVM_CAP_IRQ_ROUTING -- 2.37.1.359.gd136c6c3e2-goog
| |