mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
KVM: Add fpu get/set operations
These are really helpful when migrating an floating point app to another machine. Signed-off-by: Avi Kivity <avi@qumranet.com>
This commit is contained in:
parent
e8207547d2
commit
b8836737d9
2 changed files with 103 additions and 0 deletions
|
@ -2398,6 +2398,67 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fxsave fpu state. Taken from x86_64/processor.h. To be killed when
|
||||||
|
* we have asm/x86/processor.h
|
||||||
|
*/
|
||||||
|
struct fxsave {
|
||||||
|
u16 cwd;
|
||||||
|
u16 swd;
|
||||||
|
u16 twd;
|
||||||
|
u16 fop;
|
||||||
|
u64 rip;
|
||||||
|
u64 rdp;
|
||||||
|
u32 mxcsr;
|
||||||
|
u32 mxcsr_mask;
|
||||||
|
u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
|
||||||
|
#else
|
||||||
|
u32 xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||||
|
{
|
||||||
|
struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image;
|
||||||
|
|
||||||
|
vcpu_load(vcpu);
|
||||||
|
|
||||||
|
memcpy(fpu->fpr, fxsave->st_space, 128);
|
||||||
|
fpu->fcw = fxsave->cwd;
|
||||||
|
fpu->fsw = fxsave->swd;
|
||||||
|
fpu->ftwx = fxsave->twd;
|
||||||
|
fpu->last_opcode = fxsave->fop;
|
||||||
|
fpu->last_ip = fxsave->rip;
|
||||||
|
fpu->last_dp = fxsave->rdp;
|
||||||
|
memcpy(fpu->xmm, fxsave->xmm_space, sizeof fxsave->xmm_space);
|
||||||
|
|
||||||
|
vcpu_put(vcpu);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
|
||||||
|
{
|
||||||
|
struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image;
|
||||||
|
|
||||||
|
vcpu_load(vcpu);
|
||||||
|
|
||||||
|
memcpy(fxsave->st_space, fpu->fpr, 128);
|
||||||
|
fxsave->cwd = fpu->fcw;
|
||||||
|
fxsave->swd = fpu->fsw;
|
||||||
|
fxsave->twd = fpu->ftwx;
|
||||||
|
fxsave->fop = fpu->last_opcode;
|
||||||
|
fxsave->rip = fpu->last_ip;
|
||||||
|
fxsave->rdp = fpu->last_dp;
|
||||||
|
memcpy(fxsave->xmm_space, fpu->xmm, sizeof fxsave->xmm_space);
|
||||||
|
|
||||||
|
vcpu_put(vcpu);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static long kvm_vcpu_ioctl(struct file *filp,
|
static long kvm_vcpu_ioctl(struct file *filp,
|
||||||
unsigned int ioctl, unsigned long arg)
|
unsigned int ioctl, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -2542,6 +2603,31 @@ static long kvm_vcpu_ioctl(struct file *filp,
|
||||||
r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
|
r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case KVM_GET_FPU: {
|
||||||
|
struct kvm_fpu fpu;
|
||||||
|
|
||||||
|
memset(&fpu, 0, sizeof fpu);
|
||||||
|
r = kvm_vcpu_ioctl_get_fpu(vcpu, &fpu);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_to_user(argp, &fpu, sizeof fpu))
|
||||||
|
goto out;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KVM_SET_FPU: {
|
||||||
|
struct kvm_fpu fpu;
|
||||||
|
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_from_user(&fpu, argp, sizeof fpu))
|
||||||
|
goto out;
|
||||||
|
r = kvm_vcpu_ioctl_set_fpu(vcpu, &fpu);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,21 @@ struct kvm_regs {
|
||||||
__u64 rip, rflags;
|
__u64 rip, rflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* for KVM_GET_FPU and KVM_SET_FPU */
|
||||||
|
struct kvm_fpu {
|
||||||
|
__u8 fpr[8][16];
|
||||||
|
__u16 fcw;
|
||||||
|
__u16 fsw;
|
||||||
|
__u8 ftwx; /* in fxsave format */
|
||||||
|
__u8 pad1;
|
||||||
|
__u16 last_opcode;
|
||||||
|
__u64 last_ip;
|
||||||
|
__u64 last_dp;
|
||||||
|
__u8 xmm[16][16];
|
||||||
|
__u32 mxcsr;
|
||||||
|
__u32 pad2;
|
||||||
|
};
|
||||||
|
|
||||||
struct kvm_segment {
|
struct kvm_segment {
|
||||||
__u64 base;
|
__u64 base;
|
||||||
__u32 limit;
|
__u32 limit;
|
||||||
|
@ -285,5 +300,7 @@ struct kvm_signal_mask {
|
||||||
#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
|
#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
|
||||||
#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
|
#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
|
||||||
#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
|
#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
|
||||||
|
#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu)
|
||||||
|
#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue