diff options
author | Hollis Blanchard <hollisb@us.ibm.com> | 2007-10-31 18:24:25 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:53:00 -0500 |
commit | d075206073286dca84768137af0a0bf3d11f0663 (patch) | |
tree | 84d6883c16bba8344203df82c9cd1ee4ba013dfa /drivers/kvm/x86.c | |
parent | 8776e5194f7bb847906e3561c4dba12ed66ebfb6 (diff) |
KVM: Portability: Move x86 FPU handling to x86.c
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86.c')
-rw-r--r-- | drivers/kvm/x86.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c index 2cf7ebab50f4..ef1661f10b48 100644 --- a/drivers/kvm/x86.c +++ b/drivers/kvm/x86.c | |||
@@ -1785,3 +1785,106 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) | |||
1785 | kvm_x86_ops->skip_emulated_instruction(vcpu); | 1785 | kvm_x86_ops->skip_emulated_instruction(vcpu); |
1786 | } | 1786 | } |
1787 | EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); | 1787 | EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); |
1788 | |||
1789 | /* | ||
1790 | * fxsave fpu state. Taken from x86_64/processor.h. To be killed when | ||
1791 | * we have asm/x86/processor.h | ||
1792 | */ | ||
1793 | struct fxsave { | ||
1794 | u16 cwd; | ||
1795 | u16 swd; | ||
1796 | u16 twd; | ||
1797 | u16 fop; | ||
1798 | u64 rip; | ||
1799 | u64 rdp; | ||
1800 | u32 mxcsr; | ||
1801 | u32 mxcsr_mask; | ||
1802 | u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ | ||
1803 | #ifdef CONFIG_X86_64 | ||
1804 | u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ | ||
1805 | #else | ||
1806 | u32 xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ | ||
1807 | #endif | ||
1808 | }; | ||
1809 | |||
1810 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | ||
1811 | { | ||
1812 | struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image; | ||
1813 | |||
1814 | vcpu_load(vcpu); | ||
1815 | |||
1816 | memcpy(fpu->fpr, fxsave->st_space, 128); | ||
1817 | fpu->fcw = fxsave->cwd; | ||
1818 | fpu->fsw = fxsave->swd; | ||
1819 | fpu->ftwx = fxsave->twd; | ||
1820 | fpu->last_opcode = fxsave->fop; | ||
1821 | fpu->last_ip = fxsave->rip; | ||
1822 | fpu->last_dp = fxsave->rdp; | ||
1823 | memcpy(fpu->xmm, fxsave->xmm_space, sizeof fxsave->xmm_space); | ||
1824 | |||
1825 | vcpu_put(vcpu); | ||
1826 | |||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | ||
1831 | { | ||
1832 | struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image; | ||
1833 | |||
1834 | vcpu_load(vcpu); | ||
1835 | |||
1836 | memcpy(fxsave->st_space, fpu->fpr, 128); | ||
1837 | fxsave->cwd = fpu->fcw; | ||
1838 | fxsave->swd = fpu->fsw; | ||
1839 | fxsave->twd = fpu->ftwx; | ||
1840 | fxsave->fop = fpu->last_opcode; | ||
1841 | fxsave->rip = fpu->last_ip; | ||
1842 | fxsave->rdp = fpu->last_dp; | ||
1843 | memcpy(fxsave->xmm_space, fpu->xmm, sizeof fxsave->xmm_space); | ||
1844 | |||
1845 | vcpu_put(vcpu); | ||
1846 | |||
1847 | return 0; | ||
1848 | } | ||
1849 | |||
1850 | void fx_init(struct kvm_vcpu *vcpu) | ||
1851 | { | ||
1852 | unsigned after_mxcsr_mask; | ||
1853 | |||
1854 | /* Initialize guest FPU by resetting ours and saving into guest's */ | ||
1855 | preempt_disable(); | ||
1856 | fx_save(&vcpu->host_fx_image); | ||
1857 | fpu_init(); | ||
1858 | fx_save(&vcpu->guest_fx_image); | ||
1859 | fx_restore(&vcpu->host_fx_image); | ||
1860 | preempt_enable(); | ||
1861 | |||
1862 | vcpu->cr0 |= X86_CR0_ET; | ||
1863 | after_mxcsr_mask = offsetof(struct i387_fxsave_struct, st_space); | ||
1864 | vcpu->guest_fx_image.mxcsr = 0x1f80; | ||
1865 | memset((void *)&vcpu->guest_fx_image + after_mxcsr_mask, | ||
1866 | 0, sizeof(struct i387_fxsave_struct) - after_mxcsr_mask); | ||
1867 | } | ||
1868 | EXPORT_SYMBOL_GPL(fx_init); | ||
1869 | |||
1870 | void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) | ||
1871 | { | ||
1872 | if (!vcpu->fpu_active || vcpu->guest_fpu_loaded) | ||
1873 | return; | ||
1874 | |||
1875 | vcpu->guest_fpu_loaded = 1; | ||
1876 | fx_save(&vcpu->host_fx_image); | ||
1877 | fx_restore(&vcpu->guest_fx_image); | ||
1878 | } | ||
1879 | EXPORT_SYMBOL_GPL(kvm_load_guest_fpu); | ||
1880 | |||
1881 | void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) | ||
1882 | { | ||
1883 | if (!vcpu->guest_fpu_loaded) | ||
1884 | return; | ||
1885 | |||
1886 | vcpu->guest_fpu_loaded = 0; | ||
1887 | fx_save(&vcpu->guest_fx_image); | ||
1888 | fx_restore(&vcpu->host_fx_image); | ||
1889 | } | ||
1890 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); | ||