History

kvm: x86: Add support for getting/setting expanded xstate buffer

With KVM_CAP_XSAVE, userspace uses a hardcoded 4KB buffer to get/set xstate data from/to KVM. This doesn't work when dynamic xfeatures (e.g. AMX) are exposed to the guest as they require a larger buffer size. Introduce a new capability (KVM_CAP_XSAVE2). Userspace VMM gets the required xstate buffer size via KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2). KVM_SET_XSAVE is extended to work with both legacy and new capabilities by doing properly-sized memdup_user() based on the guest fpu container. KVM_GET_XSAVE is kept for backward-compatible reason. Instead, KVM_GET_XSAVE2 is introduced under KVM_CAP_XSAVE2 as the preferred interface for getting xstate buffer (4KB or larger size) from KVM (Link: https://lkml.org/lkml/2021/12/15/510) Also, update the api doc with the new KVM_GET_XSAVE2 ioctl.

Guang Zeng committed 4 years ago

Commit be50b201 parent c60427d6 files · +106 −5Browse files

Unified · Split

6 files
  1. Documentation/virt/kvm/api.rst +40 −2
  2. arch/x86/include/uapi/asm/kvm.h +15 −1
  3. arch/x86/kvm/cpuid.c +1 −1
  4. arch/x86/kvm/cpuid.h +2 −0
  5. arch/x86/kvm/x86.c +44 −1
  6. include/uapi/linux/kvm.h +4 −0
Documentation/virt/kvm/api.rst+40−2
@@ -1569,6 +1569,7 @@ otherwise it will return EBUSY error. · 1568 unmodified lines
15691569
15701570 struct kvm_xsave {
15711571 __u32 region[1024];
1572+ __u32 extra[0];
15721573 };
15731574
15741575 This ioctl would copy current vcpu's xsave struct to the userspace.
@@ -1577,7 +1578,7 @@ This ioctl would copy current vcpu's xsave struct to the userspace. · 2 unmodified lines
15771578 4.43 KVM_SET_XSAVE
15781579 ------------------
15791580
1580−:Capability: KVM_CAP_XSAVE
1581+:Capability: KVM_CAP_XSAVE and KVM_CAP_XSAVE2
15811582 :Architectures: x86
15821583 :Type: vcpu ioctl
15831584 :Parameters: struct kvm_xsave (in)
@@ -1588,9 +1589,18 @@ This ioctl would copy current vcpu's xsave struct to the userspace. · 4 unmodified lines
15881589
15891590 struct kvm_xsave {
15901591 __u32 region[1024];
1592+ __u32 extra[0];
15911593 };
15921594
1593−This ioctl would copy userspace's xsave struct to the kernel.
1595+This ioctl would copy userspace's xsave struct to the kernel. It copies
1596+as many bytes as are returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2),
1597+when invoked on the vm file descriptor. The size value returned by
1598+KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) will always be at least 4096.
1599+Currently, it is only greater than 4096 if a dynamic feature has been
1600+enabled with ``arch_prctl()``, but this may change in the future.
1601+
1602+The offsets of the state save areas in struct kvm_xsave follow the
1603+contents of CPUID leaf 0xD on the host.
15941604
15951605
15961606 4.44 KVM_GET_XCRS
@@ -5535,6 +5545,34 @@ the trailing ``'\0'``, is indicated by ``name_size`` in the header. · 3938 unmodified lines
55355545 The Stats Data block contains an array of 64-bit values in the same order
55365546 as the descriptors in Descriptors block.
55375547
5548+4.42 KVM_GET_XSAVE2
5549+------------------
5550+
5551+:Capability: KVM_CAP_XSAVE2
5552+:Architectures: x86
5553+:Type: vcpu ioctl
5554+:Parameters: struct kvm_xsave (out)
5555+:Returns: 0 on success, -1 on error
5556+
5557+
5558+::
5559+
5560+ struct kvm_xsave {
5561+ __u32 region[1024];
5562+ __u32 extra[0];
5563+ };
5564+
5565+This ioctl would copy current vcpu's xsave struct to the userspace. It
5566+copies as many bytes as are returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2)
5567+when invoked on the vm file descriptor. The size value returned by
5568+KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2) will always be at least 4096.
5569+Currently, it is only greater than 4096 if a dynamic feature has been
5570+enabled with ``arch_prctl()``, but this may change in the future.
5571+
5572+The offsets of the state save areas in struct kvm_xsave follow the contents
5573+of CPUID leaf 0xD on the host.
5574+
5575+
55385576 5. The kvm_run structure
55395577 ========================
55405578
arch/x86/include/uapi/asm/kvm.h+15−1
@@ -373,9 +373,23 @@ struct kvm_debugregs { · 372 unmodified lines
373373 __u64 reserved[9];
374374 };
375375
376−/* for KVM_CAP_XSAVE */
376+/* for KVM_CAP_XSAVE and KVM_CAP_XSAVE2 */
377377 struct kvm_xsave {
378+ /*
379+ * KVM_GET_XSAVE2 and KVM_SET_XSAVE write and read as many bytes
380+ * as are returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2)
381+ * respectively, when invoked on the vm file descriptor.
382+ *
383+ * The size value returned by KVM_CHECK_EXTENSION(KVM_CAP_XSAVE2)
384+ * will always be at least 4096. Currently, it is only greater
385+ * than 4096 if a dynamic feature has been enabled with
386+ * ``arch_prctl()``, but this may change in the future.
387+ *
388+ * The offsets of the state save areas in struct kvm_xsave follow
389+ * the contents of CPUID leaf 0xD on the host.
390+ */
378391 __u32 region[1024];
392+ __u32 extra[0];
379393 };
380394
381395 #define KVM_MAX_XCRS 16
arch/x86/kvm/cpuid.c+1−1
@@ -32,7 +32,7 @@ · 31 unmodified lines
3232 u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
3333 EXPORT_SYMBOL_GPL(kvm_cpu_caps);
3434
35−static u32 xstate_required_size(u64 xstate_bv, bool compacted)
35+u32 xstate_required_size(u64 xstate_bv, bool compacted)
3636 {
3737 int feature_bit = 0;
3838 u32 ret = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
arch/x86/kvm/cpuid.h+2−0
@@ -30,6 +30,8 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, · 29 unmodified lines
3030 bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
3131 u32 *ecx, u32 *edx, bool exact_only);
3232
33+u32 xstate_required_size(u64 xstate_bv, bool compacted);
34+
3335 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
3436 u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu);
3537
arch/x86/kvm/x86.c+44−1
@@ -4314,6 +4314,14 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 4313 unmodified lines
43144314 else
43154315 r = 0;
43164316 break;
4317+ case KVM_CAP_XSAVE2: {
4318+ u64 guest_perm = xstate_get_guest_group_perm();
4319+
4320+ r = xstate_required_size(supported_xcr0 & guest_perm, false);
4321+ if (r < sizeof(struct kvm_xsave))
4322+ r = sizeof(struct kvm_xsave);
4323+ break;
4324+ }
43174325 default:
43184326 break;
43194327 }
@@ -4917,6 +4925,16 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, · 597 unmodified lines
49174925 vcpu->arch.pkru);
49184926 }
49194927
4928+static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
4929+ u8 *state, unsigned int size)
4930+{
4931+ if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
4932+ return;
4933+
4934+ fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
4935+ state, size, vcpu->arch.pkru);
4936+}
4937+
49204938 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
49214939 struct kvm_xsave *guest_xsave)
49224940 {
@@ -5370,6 +5388,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 447 unmodified lines
53705388 break;
53715389 }
53725390 case KVM_GET_XSAVE: {
5391+ r = -EINVAL;
5392+ if (vcpu->arch.guest_fpu.uabi_size > sizeof(struct kvm_xsave))
5393+ break;
5394+
53735395 u.xsave = kzalloc(sizeof(struct kvm_xsave), GFP_KERNEL_ACCOUNT);
53745396 r = -ENOMEM;
53755397 if (!u.xsave)
@@ -5384,7 +5406,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 8 unmodified lines
53845406 break;
53855407 }
53865408 case KVM_SET_XSAVE: {
5387− u.xsave = memdup_user(argp, sizeof(*u.xsave));
5409+ int size = vcpu->arch.guest_fpu.uabi_size;
5410+
5411+ u.xsave = memdup_user(argp, size);
53885412 if (IS_ERR(u.xsave)) {
53895413 r = PTR_ERR(u.xsave);
53905414 goto out_nofree;
@@ -5393,6 +5417,25 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 2 unmodified lines
53935417 r = kvm_vcpu_ioctl_x86_set_xsave(vcpu, u.xsave);
53945418 break;
53955419 }
5420+
5421+ case KVM_GET_XSAVE2: {
5422+ int size = vcpu->arch.guest_fpu.uabi_size;
5423+
5424+ u.xsave = kzalloc(size, GFP_KERNEL_ACCOUNT);
5425+ r = -ENOMEM;
5426+ if (!u.xsave)
5427+ break;
5428+
5429+ kvm_vcpu_ioctl_x86_get_xsave2(vcpu, u.buffer, size);
5430+
5431+ r = -EFAULT;
5432+ if (copy_to_user(argp, u.xsave, size))
5433+ break;
5434+
5435+ r = 0;
5436+ break;
5437+ }
5438+
53965439 case KVM_GET_XCRS: {
53975440 u.xcrs = kzalloc(sizeof(struct kvm_xcrs), GFP_KERNEL_ACCOUNT);
53985441 r = -ENOMEM;
include/uapi/linux/kvm.h+4−0
@@ -1132,6 +1132,7 @@ struct kvm_ppc_resize_hpt { · 1131 unmodified lines
11321132 #define KVM_CAP_ARM_MTE 205
11331133 #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
11341134 #define KVM_CAP_VM_GPA_BITS 207
1135+#define KVM_CAP_XSAVE2 208
11351136
11361137 #ifdef KVM_CAP_IRQ_ROUTING
11371138
@@ -1622,6 +1623,9 @@ struct kvm_enc_region { · 484 unmodified lines
16221623 #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3)
16231624 #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4)
16241625
1626+/* Available with KVM_CAP_XSAVE2 */
1627+#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave)
1628+
16251629 struct kvm_s390_pv_sec_parm {
16261630 __u64 origin;
16271631 __u64 length;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t