Handle KVM_GET_{SUPPORTED,EMULATED}_CPUID in kvm_arch_vm_ioctl() so that userspace can query supported CPUID on a VM fd. When issued on a VM fd, KVM can return CPUID data tailored to the VM's type (e.g. using the TDX overlay for TDX VMs instead of the default VMX overlay). @kvm is not yet used to select the overlay; a follow-on patch will wire that up. The dev-ioctl path continues to work by passing NULL for @kvm. Extract the copy_from_user/copy_to_user boilerplate into a shared helper, kvm_get_cpuid(), used by both the dev-ioctl and VM-ioctl paths. There will a be new capability added for CPUID paranoid mode in a later patch, reuse that capability to tell userspace that the VM versions of KVM_GET_{SUPPORTED,EMULATED}_CPUID are supported. Signed-off-by: Binbin Wu --- arch/x86/kvm/cpuid.c | 7 ++++--- arch/x86/kvm/cpuid.h | 6 +++--- arch/x86/kvm/x86.c | 42 ++++++++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 938b19767feb..9634ea01d2a3 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -2013,9 +2013,10 @@ static bool sanity_check_entries(struct kvm_cpuid_entry2 __user *entries, return false; } -int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, - struct kvm_cpuid_entry2 __user *entries, - unsigned int type) +/* The input kvm could be NULL, check it before using. */ +int kvm_vm_ioctl_get_cpuid(struct kvm *kvm, struct kvm_cpuid2 *cpuid, + struct kvm_cpuid_entry2 __user *entries, + unsigned int type) { static const u32 funcs[] = { 0, 0x80000000, CENTAUR_CPUID_SIGNATURE, KVM_CPUID_SIGNATURE, diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 4b1274f055e5..0afde541b036 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -74,9 +74,9 @@ static inline struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcp function, KVM_CPUID_INDEX_NOT_SIGNIFICANT); } -int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, - struct kvm_cpuid_entry2 __user *entries, - unsigned int type); +int kvm_vm_ioctl_get_cpuid(struct kvm *kvm, struct kvm_cpuid2 *cpuid, + struct kvm_cpuid_entry2 __user *entries, + unsigned int type); int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid *cpuid, struct kvm_cpuid_entry __user *entries); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index db8434f9a2ee..525fcb09a4c0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5041,6 +5041,26 @@ static int kvm_x86_dev_has_attr(struct kvm_device_attr *attr) return __kvm_x86_dev_get_attr(attr, &val); } +static int kvm_x86_vm_get_cpuid(struct kvm *kvm, void __user *argp, unsigned int ioctl) +{ + struct kvm_cpuid2 __user *cpuid_arg = argp; + struct kvm_cpuid2 cpuid; + int r = -EFAULT; + + if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid))) + return r; + + r = kvm_vm_ioctl_get_cpuid(kvm, &cpuid, cpuid_arg->entries, ioctl); + if (r) + return r; + + r = -EFAULT; + if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid))) + return r; + + return 0; +} + long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -5076,22 +5096,7 @@ long kvm_arch_dev_ioctl(struct file *filp, } case KVM_GET_SUPPORTED_CPUID: case KVM_GET_EMULATED_CPUID: { - struct kvm_cpuid2 __user *cpuid_arg = argp; - struct kvm_cpuid2 cpuid; - - r = -EFAULT; - if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid))) - goto out; - - r = kvm_dev_ioctl_get_cpuid(&cpuid, cpuid_arg->entries, - ioctl); - if (r) - goto out; - - r = -EFAULT; - if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid))) - goto out; - r = 0; + r = kvm_x86_vm_get_cpuid(NULL, argp, ioctl); break; } case KVM_X86_GET_MCE_CAP_SUPPORTED: @@ -7628,6 +7633,11 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) r = kvm_vm_ioctl_set_msr_filter(kvm, &filter); break; } + case KVM_GET_SUPPORTED_CPUID: + case KVM_GET_EMULATED_CPUID: { + r = kvm_x86_vm_get_cpuid(kvm, argp, ioctl); + break; + } default: r = -ENOTTY; } -- 2.46.0