Skip to content

Commit 18164f6

Browse files
sean-jcbonzini
authored andcommitted
x86/fpu: Allow caller to constrain xfeatures when copying to uabi buffer
Plumb an xfeatures mask into __copy_xstate_to_uabi_buf() so that KVM can constrain which xfeatures are saved into the userspace buffer without having to modify the user_xfeatures field in KVM's guest_fpu state. KVM's ABI for KVM_GET_XSAVE{2} is that features that are not exposed to guest must not show up in the effective xstate_bv field of the buffer. Saving only the guest-supported xfeatures allows userspace to load the saved state on a different host with a fewer xfeatures, so long as the target host supports the xfeatures that are exposed to the guest. KVM currently sets user_xfeatures directly to restrict KVM_GET_XSAVE{2} to the set of guest-supported xfeatures, but doing so broke KVM's historical ABI for KVM_SET_XSAVE, which allows userspace to load any xfeatures that are supported by the *host*. Cc: [email protected] Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 4bcd9bc commit 18164f6

File tree

5 files changed

+21
-18
lines changed

5 files changed

+21
-18
lines changed

arch/x86/include/asm/fpu/api.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ static inline void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd) {
157157
static inline void fpu_sync_guest_vmexit_xfd_state(void) { }
158158
#endif
159159

160-
extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, unsigned int size, u32 pkru);
160+
extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
161+
unsigned int size, u64 xfeatures, u32 pkru);
161162
extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru);
162163

163164
static inline void fpstate_set_confidential(struct fpu_guest *gfpu)

arch/x86/kernel/fpu/core.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,14 +369,15 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest)
369369
EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpstate);
370370

371371
void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
372-
unsigned int size, u32 pkru)
372+
unsigned int size, u64 xfeatures, u32 pkru)
373373
{
374374
struct fpstate *kstate = gfpu->fpstate;
375375
union fpregs_state *ustate = buf;
376376
struct membuf mb = { .p = buf, .left = size };
377377

378378
if (cpu_feature_enabled(X86_FEATURE_XSAVE)) {
379-
__copy_xstate_to_uabi_buf(mb, kstate, pkru, XSTATE_COPY_XSAVE);
379+
__copy_xstate_to_uabi_buf(mb, kstate, xfeatures, pkru,
380+
XSTATE_COPY_XSAVE);
380381
} else {
381382
memcpy(&ustate->fxsave, &kstate->regs.fxsave,
382383
sizeof(ustate->fxsave));

arch/x86/kernel/fpu/xstate.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,7 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
10491049
* __copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer
10501050
* @to: membuf descriptor
10511051
* @fpstate: The fpstate buffer from which to copy
1052+
* @xfeatures: The mask of xfeatures to save (XSAVE mode only)
10521053
* @pkru_val: The PKRU value to store in the PKRU component
10531054
* @copy_mode: The requested copy mode
10541055
*
@@ -1059,7 +1060,8 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate,
10591060
* It supports partial copy but @to.pos always starts from zero.
10601061
*/
10611062
void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
1062-
u32 pkru_val, enum xstate_copy_mode copy_mode)
1063+
u64 xfeatures, u32 pkru_val,
1064+
enum xstate_copy_mode copy_mode)
10631065
{
10641066
const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr);
10651067
struct xregs_state *xinit = &init_fpstate.regs.xsave;
@@ -1083,7 +1085,7 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
10831085
break;
10841086

10851087
case XSTATE_COPY_XSAVE:
1086-
header.xfeatures &= fpstate->user_xfeatures;
1088+
header.xfeatures &= fpstate->user_xfeatures & xfeatures;
10871089
break;
10881090
}
10891091

@@ -1185,6 +1187,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
11851187
enum xstate_copy_mode copy_mode)
11861188
{
11871189
__copy_xstate_to_uabi_buf(to, tsk->thread.fpu.fpstate,
1190+
tsk->thread.fpu.fpstate->user_xfeatures,
11881191
tsk->thread.pkru, copy_mode);
11891192
}
11901193

arch/x86/kernel/fpu/xstate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ enum xstate_copy_mode {
4343

4444
struct membuf;
4545
extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
46-
u32 pkru_val, enum xstate_copy_mode copy_mode);
46+
u64 xfeatures, u32 pkru_val,
47+
enum xstate_copy_mode copy_mode);
4748
extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
4849
enum xstate_copy_mode mode);
4950
extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru);

arch/x86/kvm/x86.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5382,26 +5382,23 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
53825382
return 0;
53835383
}
53845384

5385-
static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
5386-
struct kvm_xsave *guest_xsave)
5385+
5386+
static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
5387+
u8 *state, unsigned int size)
53875388
{
53885389
if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
53895390
return;
53905391

5391-
fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
5392-
guest_xsave->region,
5393-
sizeof(guest_xsave->region),
5392+
fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size,
5393+
vcpu->arch.guest_fpu.fpstate->user_xfeatures,
53945394
vcpu->arch.pkru);
53955395
}
53965396

5397-
static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
5398-
u8 *state, unsigned int size)
5397+
static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
5398+
struct kvm_xsave *guest_xsave)
53995399
{
5400-
if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
5401-
return;
5402-
5403-
fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
5404-
state, size, vcpu->arch.pkru);
5400+
return kvm_vcpu_ioctl_x86_get_xsave2(vcpu, (void *)guest_xsave->region,
5401+
sizeof(guest_xsave->region));
54055402
}
54065403

54075404
static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,

0 commit comments

Comments
 (0)