Skip to content

Commit 2bc3997

Browse files
vittyvkbonzini
authored andcommitted
x86/kvm/hyper-v: Introduce KVM_GET_SUPPORTED_HV_CPUID
With every new Hyper-V Enlightenment we implement we're forced to add a KVM_CAP_HYPERV_* capability. While this approach works it is fairly inconvenient: the majority of the enlightenments we do have corresponding CPUID feature bit(s) and userspace has to know this anyways to be able to expose the feature to the guest. Add KVM_GET_SUPPORTED_HV_CPUID ioctl (backed by KVM_CAP_HYPERV_CPUID, "one cap to rule them all!") returning all Hyper-V CPUID feature leaves. Using the existing KVM_GET_SUPPORTED_CPUID doesn't seem to be possible: Hyper-V CPUID feature leaves intersect with KVM's (e.g. 0x40000000, 0x40000001) and we would probably confuse userspace in case we decide to return these twice. KVM_CAP_HYPERV_CPUID's number is interim: we're intended to drop KVM_CAP_HYPERV_STIMER_DIRECT and use its number instead. Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent e2e871a commit 2bc3997

File tree

5 files changed

+203
-0
lines changed

5 files changed

+203
-0
lines changed

Documentation/virtual/kvm/api.txt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,62 @@ is enabled; for more information, see the description of the capability.
38003800
However, it can always be used as long as KVM_CHECK_EXTENSION confirms
38013801
that KVM_CAP_MANUAL_DIRTY_LOG_PROTECT is present.
38023802

3803+
4.118 KVM_GET_SUPPORTED_HV_CPUID
3804+
3805+
Capability: KVM_CAP_HYPERV_CPUID
3806+
Architectures: x86
3807+
Type: vcpu ioctl
3808+
Parameters: struct kvm_cpuid2 (in/out)
3809+
Returns: 0 on success, -1 on error
3810+
3811+
struct kvm_cpuid2 {
3812+
__u32 nent;
3813+
__u32 padding;
3814+
struct kvm_cpuid_entry2 entries[0];
3815+
};
3816+
3817+
struct kvm_cpuid_entry2 {
3818+
__u32 function;
3819+
__u32 index;
3820+
__u32 flags;
3821+
__u32 eax;
3822+
__u32 ebx;
3823+
__u32 ecx;
3824+
__u32 edx;
3825+
__u32 padding[3];
3826+
};
3827+
3828+
This ioctl returns x86 cpuid features leaves related to Hyper-V emulation in
3829+
KVM. Userspace can use the information returned by this ioctl to construct
3830+
cpuid information presented to guests consuming Hyper-V enlightenments (e.g.
3831+
Windows or Hyper-V guests).
3832+
3833+
CPUID feature leaves returned by this ioctl are defined by Hyper-V Top Level
3834+
Functional Specification (TLFS). These leaves can't be obtained with
3835+
KVM_GET_SUPPORTED_CPUID ioctl because some of them intersect with KVM feature
3836+
leaves (0x40000000, 0x40000001).
3837+
3838+
Currently, the following list of CPUID leaves are returned:
3839+
HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
3840+
HYPERV_CPUID_INTERFACE
3841+
HYPERV_CPUID_VERSION
3842+
HYPERV_CPUID_FEATURES
3843+
HYPERV_CPUID_ENLIGHTMENT_INFO
3844+
HYPERV_CPUID_IMPLEMENT_LIMITS
3845+
HYPERV_CPUID_NESTED_FEATURES
3846+
3847+
HYPERV_CPUID_NESTED_FEATURES leaf is only exposed when Enlightened VMCS was
3848+
enabled on the corresponding vCPU (KVM_CAP_HYPERV_ENLIGHTENED_VMCS).
3849+
3850+
Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
3851+
with the 'nent' field indicating the number of entries in the variable-size
3852+
array 'entries'. If the number of entries is too low to describe all Hyper-V
3853+
feature leaves, an error (E2BIG) is returned. If the number is more or equal
3854+
to the number of Hyper-V feature leaves, the 'nent' field is adjusted to the
3855+
number of valid entries in the 'entries' array, which is then filled.
3856+
3857+
'index' and 'flags' fields in 'struct kvm_cpuid_entry2' are currently reserved,
3858+
userspace should not expect to get any particular value there.
38033859

38043860
5. The kvm_run structure
38053861
------------------------

arch/x86/kvm/hyperv.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,3 +1752,124 @@ int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args)
17521752
return kvm_hv_eventfd_deassign(kvm, args->conn_id);
17531753
return kvm_hv_eventfd_assign(kvm, args->conn_id, args->fd);
17541754
}
1755+
1756+
int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
1757+
struct kvm_cpuid_entry2 __user *entries)
1758+
{
1759+
uint16_t evmcs_ver = kvm_x86_ops->nested_get_evmcs_version(vcpu);
1760+
struct kvm_cpuid_entry2 cpuid_entries[] = {
1761+
{ .function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS },
1762+
{ .function = HYPERV_CPUID_INTERFACE },
1763+
{ .function = HYPERV_CPUID_VERSION },
1764+
{ .function = HYPERV_CPUID_FEATURES },
1765+
{ .function = HYPERV_CPUID_ENLIGHTMENT_INFO },
1766+
{ .function = HYPERV_CPUID_IMPLEMENT_LIMITS },
1767+
{ .function = HYPERV_CPUID_NESTED_FEATURES },
1768+
};
1769+
int i, nent = ARRAY_SIZE(cpuid_entries);
1770+
1771+
/* Skip NESTED_FEATURES if eVMCS is not supported */
1772+
if (!evmcs_ver)
1773+
--nent;
1774+
1775+
if (cpuid->nent < nent)
1776+
return -E2BIG;
1777+
1778+
if (cpuid->nent > nent)
1779+
cpuid->nent = nent;
1780+
1781+
for (i = 0; i < nent; i++) {
1782+
struct kvm_cpuid_entry2 *ent = &cpuid_entries[i];
1783+
u32 signature[3];
1784+
1785+
switch (ent->function) {
1786+
case HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS:
1787+
memcpy(signature, "Linux KVM Hv", 12);
1788+
1789+
ent->eax = HYPERV_CPUID_NESTED_FEATURES;
1790+
ent->ebx = signature[0];
1791+
ent->ecx = signature[1];
1792+
ent->edx = signature[2];
1793+
break;
1794+
1795+
case HYPERV_CPUID_INTERFACE:
1796+
memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
1797+
ent->eax = signature[0];
1798+
break;
1799+
1800+
case HYPERV_CPUID_VERSION:
1801+
/*
1802+
* We implement some Hyper-V 2016 functions so let's use
1803+
* this version.
1804+
*/
1805+
ent->eax = 0x00003839;
1806+
ent->ebx = 0x000A0000;
1807+
break;
1808+
1809+
case HYPERV_CPUID_FEATURES:
1810+
ent->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
1811+
ent->eax |= HV_MSR_TIME_REF_COUNT_AVAILABLE;
1812+
ent->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
1813+
ent->eax |= HV_MSR_SYNTIMER_AVAILABLE;
1814+
ent->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
1815+
ent->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
1816+
ent->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
1817+
ent->eax |= HV_X64_MSR_RESET_AVAILABLE;
1818+
ent->eax |= HV_MSR_REFERENCE_TSC_AVAILABLE;
1819+
ent->eax |= HV_X64_MSR_GUEST_IDLE_AVAILABLE;
1820+
ent->eax |= HV_X64_ACCESS_FREQUENCY_MSRS;
1821+
ent->eax |= HV_X64_ACCESS_REENLIGHTENMENT;
1822+
1823+
ent->ebx |= HV_X64_POST_MESSAGES;
1824+
ent->ebx |= HV_X64_SIGNAL_EVENTS;
1825+
1826+
ent->edx |= HV_FEATURE_FREQUENCY_MSRS_AVAILABLE;
1827+
ent->edx |= HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE;
1828+
ent->edx |= HV_STIMER_DIRECT_MODE_AVAILABLE;
1829+
1830+
break;
1831+
1832+
case HYPERV_CPUID_ENLIGHTMENT_INFO:
1833+
ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
1834+
ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
1835+
ent->eax |= HV_X64_SYSTEM_RESET_RECOMMENDED;
1836+
ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
1837+
ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
1838+
ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED;
1839+
ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
1840+
1841+
/*
1842+
* Default number of spinlock retry attempts, matches
1843+
* HyperV 2016.
1844+
*/
1845+
ent->ebx = 0x00000FFF;
1846+
1847+
break;
1848+
1849+
case HYPERV_CPUID_IMPLEMENT_LIMITS:
1850+
/* Maximum number of virtual processors */
1851+
ent->eax = KVM_MAX_VCPUS;
1852+
/*
1853+
* Maximum number of logical processors, matches
1854+
* HyperV 2016.
1855+
*/
1856+
ent->ebx = 64;
1857+
1858+
break;
1859+
1860+
case HYPERV_CPUID_NESTED_FEATURES:
1861+
ent->eax = evmcs_ver;
1862+
1863+
break;
1864+
1865+
default:
1866+
break;
1867+
}
1868+
}
1869+
1870+
if (copy_to_user(entries, cpuid_entries,
1871+
nent * sizeof(struct kvm_cpuid_entry2)))
1872+
return -EFAULT;
1873+
1874+
return 0;
1875+
}

arch/x86/kvm/hyperv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,7 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm,
9797
void kvm_hv_init_vm(struct kvm *kvm);
9898
void kvm_hv_destroy_vm(struct kvm *kvm);
9999
int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args);
100+
int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
101+
struct kvm_cpuid_entry2 __user *entries);
100102

101103
#endif

arch/x86/kvm/x86.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
29972997
case KVM_CAP_HYPERV_TLBFLUSH:
29982998
case KVM_CAP_HYPERV_SEND_IPI:
29992999
case KVM_CAP_HYPERV_ENLIGHTENED_VMCS:
3000+
case KVM_CAP_HYPERV_CPUID:
30003001
case KVM_CAP_PCI_SEGMENT:
30013002
case KVM_CAP_DEBUGREGS:
30023003
case KVM_CAP_X86_ROBUST_SINGLESTEP:
@@ -4191,6 +4192,25 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
41914192
r = kvm_x86_ops->set_nested_state(vcpu, user_kvm_nested_state, &kvm_state);
41924193
break;
41934194
}
4195+
case KVM_GET_SUPPORTED_HV_CPUID: {
4196+
struct kvm_cpuid2 __user *cpuid_arg = argp;
4197+
struct kvm_cpuid2 cpuid;
4198+
4199+
r = -EFAULT;
4200+
if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid)))
4201+
goto out;
4202+
4203+
r = kvm_vcpu_ioctl_get_hv_cpuid(vcpu, &cpuid,
4204+
cpuid_arg->entries);
4205+
if (r)
4206+
goto out;
4207+
4208+
r = -EFAULT;
4209+
if (copy_to_user(cpuid_arg, &cpuid, sizeof(cpuid)))
4210+
goto out;
4211+
r = 0;
4212+
break;
4213+
}
41944214
default:
41954215
r = -EINVAL;
41964216
}

include/uapi/linux/kvm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ struct kvm_ppc_resize_hpt {
987987
#define KVM_CAP_EXCEPTION_PAYLOAD 164
988988
#define KVM_CAP_ARM_VM_IPA_SIZE 165
989989
#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
990+
#define KVM_CAP_HYPERV_CPUID 167
990991

991992
#ifdef KVM_CAP_IRQ_ROUTING
992993

@@ -1436,6 +1437,9 @@ struct kvm_enc_region {
14361437
/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT */
14371438
#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
14381439

1440+
/* Available with KVM_CAP_HYPERV_CPUID */
1441+
#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
1442+
14391443
/* Secure Encrypted Virtualization command */
14401444
enum sev_cmd_id {
14411445
/* Guest initialization commands */

0 commit comments

Comments
 (0)