Loading drivers/kvm/kvm_main.c +86 −0 Original line number Original line Diff line number Diff line Loading @@ -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) { { Loading Loading @@ -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: ; ; } } Loading include/linux/kvm.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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
drivers/kvm/kvm_main.c +86 −0 Original line number Original line Diff line number Diff line Loading @@ -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) { { Loading Loading @@ -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: ; ; } } Loading
include/linux/kvm.h +17 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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