Skip to content

Commit dd6e631

Browse files
committed
KVM: x86: add system attribute to retrieve full set of supported xsave states
Because KVM_GET_SUPPORTED_CPUID is meant to be passed (by simple-minded VMMs) to KVM_SET_CPUID2, it cannot include any dynamic xsave states that have not been enabled. Probing those, for example so that they can be passed to ARCH_REQ_XCOMP_GUEST_PERM, requires a new ioctl or arch_prctl. The latter is in fact worse, even though that is what the rest of the API uses, because it would require supported_xcr0 to be moved from the KVM module to the kernel just for this use. In addition, the value would be nonsensical (or an error would have to be returned) until the KVM module is loaded in. Therefore, to limit the growth of system ioctls, add a /dev/kvm variant of KVM_{GET,HAS}_DEVICE_ATTR, and implement it in x86 with just one group (0) and attribute (KVM_X86_XCOMP_GUEST_SUPP). Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 56f289a commit dd6e631

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3268,6 +3268,7 @@ number.
32683268

32693269
:Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
32703270
KVM_CAP_VCPU_ATTRIBUTES for vcpu device
3271+
KVM_CAP_SYS_ATTRIBUTES for system (/dev/kvm) device (no set)
32713272
:Type: device ioctl, vm ioctl, vcpu ioctl
32723273
:Parameters: struct kvm_device_attr
32733274
:Returns: 0 on success, -1 on error
@@ -3302,7 +3303,8 @@ transferred is defined by the particular attribute.
33023303
------------------------
33033304

33043305
:Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
3305-
KVM_CAP_VCPU_ATTRIBUTES for vcpu device
3306+
KVM_CAP_VCPU_ATTRIBUTES for vcpu device
3307+
KVM_CAP_SYS_ATTRIBUTES for system (/dev/kvm) device
33063308
:Type: device ioctl, vm ioctl, vcpu ioctl
33073309
:Parameters: struct kvm_device_attr
33083310
:Returns: 0 on success, -1 on error

arch/x86/include/uapi/asm/kvm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ struct kvm_sync_regs {
452452

453453
#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
454454

455+
/* attributes for system fd (group 0) */
456+
#define KVM_X86_XCOMP_GUEST_SUPP 0
457+
455458
struct kvm_vmx_nested_state_data {
456459
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
457460
__u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];

arch/x86/kvm/x86.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4230,6 +4230,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
42304230
case KVM_CAP_SREGS2:
42314231
case KVM_CAP_EXIT_ON_EMULATION_FAILURE:
42324232
case KVM_CAP_VCPU_ATTRIBUTES:
4233+
case KVM_CAP_SYS_ATTRIBUTES:
42334234
r = 1;
42344235
break;
42354236
case KVM_CAP_EXIT_HYPERCALL:
@@ -4343,6 +4344,40 @@ static inline void __user *kvm_get_attr_addr(struct kvm_device_attr *attr)
43434344
return uaddr;
43444345
}
43454346

4347+
static int kvm_x86_dev_get_attr(struct kvm_device_attr *attr)
4348+
{
4349+
u64 __user *uaddr = kvm_get_attr_addr(attr);
4350+
4351+
if (attr->group)
4352+
return -ENXIO;
4353+
4354+
if (IS_ERR(uaddr))
4355+
return PTR_ERR(uaddr);
4356+
4357+
switch (attr->attr) {
4358+
case KVM_X86_XCOMP_GUEST_SUPP:
4359+
if (put_user(supported_xcr0, uaddr))
4360+
return -EFAULT;
4361+
return 0;
4362+
default:
4363+
return -ENXIO;
4364+
break;
4365+
}
4366+
}
4367+
4368+
static int kvm_x86_dev_has_attr(struct kvm_device_attr *attr)
4369+
{
4370+
if (attr->group)
4371+
return -ENXIO;
4372+
4373+
switch (attr->attr) {
4374+
case KVM_X86_XCOMP_GUEST_SUPP:
4375+
return 0;
4376+
default:
4377+
return -ENXIO;
4378+
}
4379+
}
4380+
43464381
long kvm_arch_dev_ioctl(struct file *filp,
43474382
unsigned int ioctl, unsigned long arg)
43484383
{
@@ -4431,6 +4466,22 @@ long kvm_arch_dev_ioctl(struct file *filp,
44314466
case KVM_GET_SUPPORTED_HV_CPUID:
44324467
r = kvm_ioctl_get_supported_hv_cpuid(NULL, argp);
44334468
break;
4469+
case KVM_GET_DEVICE_ATTR: {
4470+
struct kvm_device_attr attr;
4471+
r = -EFAULT;
4472+
if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
4473+
break;
4474+
r = kvm_x86_dev_get_attr(&attr);
4475+
break;
4476+
}
4477+
case KVM_HAS_DEVICE_ATTR: {
4478+
struct kvm_device_attr attr;
4479+
r = -EFAULT;
4480+
if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
4481+
break;
4482+
r = kvm_x86_dev_has_attr(&attr);
4483+
break;
4484+
}
44344485
default:
44354486
r = -EINVAL;
44364487
break;

include/uapi/linux/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,7 @@ struct kvm_ppc_resize_hpt {
11331133
#define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
11341134
#define KVM_CAP_VM_GPA_BITS 207
11351135
#define KVM_CAP_XSAVE2 208
1136+
#define KVM_CAP_SYS_ATTRIBUTES 209
11361137

11371138
#ifdef KVM_CAP_IRQ_ROUTING
11381139

0 commit comments

Comments
 (0)