]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0015-x86-fpu-Allow-caller-to-constrain-xfeatures-when-cop.patch
e4837b918a5801bcbc88ca37d8054a163b875327
[pve-kernel.git] / patches / kernel / 0015-x86-fpu-Allow-caller-to-constrain-xfeatures-when-cop.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Sean Christopherson <seanjc@google.com>
3 Date: Wed, 27 Sep 2023 17:19:52 -0700
4 Subject: [PATCH] x86/fpu: Allow caller to constrain xfeatures when copying to
5 uabi buffer
6
7 Plumb an xfeatures mask into __copy_xstate_to_uabi_buf() so that KVM can
8 constrain which xfeatures are saved into the userspace buffer without
9 having to modify the user_xfeatures field in KVM's guest_fpu state.
10
11 KVM's ABI for KVM_GET_XSAVE{2} is that features that are not exposed to
12 guest must not show up in the effective xstate_bv field of the buffer.
13 Saving only the guest-supported xfeatures allows userspace to load the
14 saved state on a different host with a fewer xfeatures, so long as the
15 target host supports the xfeatures that are exposed to the guest.
16
17 KVM currently sets user_xfeatures directly to restrict KVM_GET_XSAVE{2} to
18 the set of guest-supported xfeatures, but doing so broke KVM's historical
19 ABI for KVM_SET_XSAVE, which allows userspace to load any xfeatures that
20 are supported by the *host*.
21
22 Cc: stable@vger.kernel.org
23 Signed-off-by: Sean Christopherson <seanjc@google.com>
24 Message-Id: <20230928001956.924301-2-seanjc@google.com>
25 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
26 (cherry picked from commit 18164f66e6c59fda15c198b371fa008431efdb22)
27 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
28 ---
29 arch/x86/include/asm/fpu/api.h | 3 ++-
30 arch/x86/kernel/fpu/core.c | 5 +++--
31 arch/x86/kernel/fpu/xstate.c | 7 +++++--
32 arch/x86/kernel/fpu/xstate.h | 3 ++-
33 arch/x86/kvm/x86.c | 21 +++++++++------------
34 5 files changed, 21 insertions(+), 18 deletions(-)
35
36 diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
37 index b475d9a582b8..e829fa4c6788 100644
38 --- a/arch/x86/include/asm/fpu/api.h
39 +++ b/arch/x86/include/asm/fpu/api.h
40 @@ -148,7 +148,8 @@ static inline void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd) {
41 static inline void fpu_sync_guest_vmexit_xfd_state(void) { }
42 #endif
43
44 -extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, unsigned int size, u32 pkru);
45 +extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
46 + unsigned int size, u64 xfeatures, u32 pkru);
47 extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru);
48
49 static inline void fpstate_set_confidential(struct fpu_guest *gfpu)
50 diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
51 index 98e507cc7d34..b582325b9c37 100644
52 --- a/arch/x86/kernel/fpu/core.c
53 +++ b/arch/x86/kernel/fpu/core.c
54 @@ -369,14 +369,15 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest)
55 EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpstate);
56
57 void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
58 - unsigned int size, u32 pkru)
59 + unsigned int size, u64 xfeatures, u32 pkru)
60 {
61 struct fpstate *kstate = gfpu->fpstate;
62 union fpregs_state *ustate = buf;
63 struct membuf mb = { .p = buf, .left = size };
64
65 if (cpu_feature_enabled(X86_FEATURE_XSAVE)) {
66 - __copy_xstate_to_uabi_buf(mb, kstate, pkru, XSTATE_COPY_XSAVE);
67 + __copy_xstate_to_uabi_buf(mb, kstate, xfeatures, pkru,
68 + XSTATE_COPY_XSAVE);
69 } else {
70 memcpy(&ustate->fxsave, &kstate->regs.fxsave,
71 sizeof(ustate->fxsave));
72 diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
73 index 1afbc4866b10..463ec0cd0dab 100644
74 --- a/arch/x86/kernel/fpu/xstate.c
75 +++ b/arch/x86/kernel/fpu/xstate.c
76 @@ -1053,6 +1053,7 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
77 * __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer
78 * @to: membuf descriptor
79 * @fpstate: The fpstate buffer from which to copy
80 + * @xfeatures: The mask of xfeatures to save (XSAVE mode only)
81 * @pkru_val: The PKRU value to store in the PKRU component
82 * @copy_mode: The requested copy mode
83 *
84 @@ -1063,7 +1064,8 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
85 * It supports partial copy but @to.pos always starts from zero.
86 */
87 void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
88 - u32 pkru_val, enum xstate_copy_mode copy_mode)
89 + u64 xfeatures, u32 pkru_val,
90 + enum xstate_copy_mode copy_mode)
91 {
92 const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr);
93 struct xregs_state *xinit = &init_fpstate.regs.xsave;
94 @@ -1087,7 +1089,7 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
95 break;
96
97 case XSTATE_COPY_XSAVE:
98 - header.xfeatures &= fpstate->user_xfeatures;
99 + header.xfeatures &= fpstate->user_xfeatures & xfeatures;
100 break;
101 }
102
103 @@ -1189,6 +1191,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
104 enum xstate_copy_mode copy_mode)
105 {
106 __copy_xstate_to_uabi_buf(to, tsk->thread.fpu.fpstate,
107 + tsk->thread.fpu.fpstate->user_xfeatures,
108 tsk->thread.pkru, copy_mode);
109 }
110
111 diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
112 index a4ecb04d8d64..3518fb26d06b 100644
113 --- a/arch/x86/kernel/fpu/xstate.h
114 +++ b/arch/x86/kernel/fpu/xstate.h
115 @@ -43,7 +43,8 @@ enum xstate_copy_mode {
116
117 struct membuf;
118 extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
119 - u32 pkru_val, enum xstate_copy_mode copy_mode);
120 + u64 xfeatures, u32 pkru_val,
121 + enum xstate_copy_mode copy_mode);
122 extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
123 enum xstate_copy_mode mode);
124 extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru);
125 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
126 index 6690a3722007..394d3a8b4682 100644
127 --- a/arch/x86/kvm/x86.c
128 +++ b/arch/x86/kvm/x86.c
129 @@ -5385,26 +5385,23 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
130 return 0;
131 }
132
133 -static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
134 - struct kvm_xsave *guest_xsave)
135 +
136 +static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
137 + u8 *state, unsigned int size)
138 {
139 if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
140 return;
141
142 - fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
143 - guest_xsave->region,
144 - sizeof(guest_xsave->region),
145 + fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size,
146 + vcpu->arch.guest_fpu.fpstate->user_xfeatures,
147 vcpu->arch.pkru);
148 }
149
150 -static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
151 - u8 *state, unsigned int size)
152 +static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
153 + struct kvm_xsave *guest_xsave)
154 {
155 - if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
156 - return;
157 -
158 - fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
159 - state, size, vcpu->arch.pkru);
160 + return kvm_vcpu_ioctl_x86_get_xsave2(vcpu, (void *)guest_xsave->region,
161 + sizeof(guest_xsave->region));
162 }
163
164 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,