aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h3
-rw-r--r--drivers/kvm/kvm_main.c107
-rw-r--r--drivers/kvm/x86.c103
3 files changed, 108 insertions, 105 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index ef2a6a8328e..469ca42c2a1 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -633,6 +633,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
633 unsigned int ioctl, unsigned long arg); 633 unsigned int ioctl, unsigned long arg);
634void kvm_arch_destroy_vm(struct kvm *kvm); 634void kvm_arch_destroy_vm(struct kvm *kvm);
635 635
636int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
637int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
638
636__init void kvm_arch_init(void); 639__init void kvm_arch_init(void);
637 640
638static inline void kvm_guest_enter(void) 641static inline void kvm_guest_enter(void)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 57573ebf02b..7230f48ba08 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -73,28 +73,6 @@ static inline int valid_vcpu(int n)
73 return likely(n >= 0 && n < KVM_MAX_VCPUS); 73 return likely(n >= 0 && n < KVM_MAX_VCPUS);
74} 74}
75 75
76void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
77{
78 if (!vcpu->fpu_active || vcpu->guest_fpu_loaded)
79 return;
80
81 vcpu->guest_fpu_loaded = 1;
82 fx_save(&vcpu->host_fx_image);
83 fx_restore(&vcpu->guest_fx_image);
84}
85EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
86
87void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
88{
89 if (!vcpu->guest_fpu_loaded)
90 return;
91
92 vcpu->guest_fpu_loaded = 0;
93 fx_save(&vcpu->guest_fx_image);
94 fx_restore(&vcpu->host_fx_image);
95}
96EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
97
98/* 76/*
99 * Switches to specified vcpu, until a matching vcpu_put() 77 * Switches to specified vcpu, until a matching vcpu_put()
100 */ 78 */
@@ -294,26 +272,6 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
294 return 0; 272 return 0;
295} 273}
296 274
297void fx_init(struct kvm_vcpu *vcpu)
298{
299 unsigned after_mxcsr_mask;
300
301 /* Initialize guest FPU by resetting ours and saving into guest's */
302 preempt_disable();
303 fx_save(&vcpu->host_fx_image);
304 fpu_init();
305 fx_save(&vcpu->guest_fx_image);
306 fx_restore(&vcpu->host_fx_image);
307 preempt_enable();
308
309 vcpu->cr0 |= X86_CR0_ET;
310 after_mxcsr_mask = offsetof(struct i387_fxsave_struct, st_space);
311 vcpu->guest_fx_image.mxcsr = 0x1f80;
312 memset((void *)&vcpu->guest_fx_image + after_mxcsr_mask,
313 0, sizeof(struct i387_fxsave_struct) - after_mxcsr_mask);
314}
315EXPORT_SYMBOL_GPL(fx_init);
316
317/* 275/*
318 * Allocate some memory and give it an address in the guest physical address 276 * Allocate some memory and give it an address in the guest physical address
319 * space. 277 * space.
@@ -1422,67 +1380,6 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
1422 return 0; 1380 return 0;
1423} 1381}
1424 1382
1425/*
1426 * fxsave fpu state. Taken from x86_64/processor.h. To be killed when
1427 * we have asm/x86/processor.h
1428 */
1429struct fxsave {
1430 u16 cwd;
1431 u16 swd;
1432 u16 twd;
1433 u16 fop;
1434 u64 rip;
1435 u64 rdp;
1436 u32 mxcsr;
1437 u32 mxcsr_mask;
1438 u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
1439#ifdef CONFIG_X86_64
1440 u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
1441#else
1442 u32 xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
1443#endif
1444};
1445
1446static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
1447{
1448 struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image;
1449
1450 vcpu_load(vcpu);
1451
1452 memcpy(fpu->fpr, fxsave->st_space, 128);
1453 fpu->fcw = fxsave->cwd;
1454 fpu->fsw = fxsave->swd;
1455 fpu->ftwx = fxsave->twd;
1456 fpu->last_opcode = fxsave->fop;
1457 fpu->last_ip = fxsave->rip;
1458 fpu->last_dp = fxsave->rdp;
1459 memcpy(fpu->xmm, fxsave->xmm_space, sizeof fxsave->xmm_space);
1460
1461 vcpu_put(vcpu);
1462
1463 return 0;
1464}
1465
1466static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
1467{
1468 struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image;
1469
1470 vcpu_load(vcpu);
1471
1472 memcpy(fxsave->st_space, fpu->fpr, 128);
1473 fxsave->cwd = fpu->fcw;
1474 fxsave->swd = fpu->fsw;
1475 fxsave->twd = fpu->ftwx;
1476 fxsave->fop = fpu->last_opcode;
1477 fxsave->rip = fpu->last_ip;
1478 fxsave->rdp = fpu->last_dp;
1479 memcpy(fxsave->xmm_space, fpu->xmm, sizeof fxsave->xmm_space);
1480
1481 vcpu_put(vcpu);
1482
1483 return 0;
1484}
1485
1486static long kvm_vcpu_ioctl(struct file *filp, 1383static long kvm_vcpu_ioctl(struct file *filp,
1487 unsigned int ioctl, unsigned long arg) 1384 unsigned int ioctl, unsigned long arg)
1488{ 1385{
@@ -1613,7 +1510,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
1613 struct kvm_fpu fpu; 1510 struct kvm_fpu fpu;
1614 1511
1615 memset(&fpu, 0, sizeof fpu); 1512 memset(&fpu, 0, sizeof fpu);
1616 r = kvm_vcpu_ioctl_get_fpu(vcpu, &fpu); 1513 r = kvm_arch_vcpu_ioctl_get_fpu(vcpu, &fpu);
1617 if (r) 1514 if (r)
1618 goto out; 1515 goto out;
1619 r = -EFAULT; 1516 r = -EFAULT;
@@ -1628,7 +1525,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
1628 r = -EFAULT; 1525 r = -EFAULT;
1629 if (copy_from_user(&fpu, argp, sizeof fpu)) 1526 if (copy_from_user(&fpu, argp, sizeof fpu))
1630 goto out; 1527 goto out;
1631 r = kvm_vcpu_ioctl_set_fpu(vcpu, &fpu); 1528 r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, &fpu);
1632 if (r) 1529 if (r)
1633 goto out; 1530 goto out;
1634 r = 0; 1531 r = 0;
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 2cf7ebab50f..ef1661f10b4 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}
1787EXPORT_SYMBOL_GPL(kvm_emulate_cpuid); 1787EXPORT_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 */
1793struct 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
1810int 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
1830int 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
1850void 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}
1868EXPORT_SYMBOL_GPL(fx_init);
1869
1870void 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}
1879EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
1880
1881void 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}
1890EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);