aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-07-30 07:13:43 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:21 -0400
commitb114b0804df7131cb6764b948c1c530c834fa3c0 (patch)
tree4e5ced9ed1cdb673d27b26b166cd0bd7c845d5b9 /drivers
parentc16f862d0257349607b7a9be7b4a4b7ed419a3ab (diff)
KVM: Use alignment properties of vcpu to simplify FPU ops
Now we use a kmem cache for allocating vcpus, we can get the 16-byte alignment required by fxsave & fxrstor instructions, and avoid manually aligning the buffer. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/kvm.h13
-rw-r--r--drivers/kvm/kvm_main.c45
-rw-r--r--drivers/kvm/svm.c8
3 files changed, 25 insertions, 41 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index b362e8f8f832..7a34706f42be 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -45,10 +45,6 @@
45#define KVM_REFILL_PAGES 25 45#define KVM_REFILL_PAGES 25
46#define KVM_MAX_CPUID_ENTRIES 40 46#define KVM_MAX_CPUID_ENTRIES 40
47 47
48#define FX_IMAGE_SIZE 512
49#define FX_IMAGE_ALIGN 16
50#define FX_BUF_SIZE (2 * FX_IMAGE_SIZE + FX_IMAGE_ALIGN)
51
52#define DE_VECTOR 0 48#define DE_VECTOR 0
53#define NM_VECTOR 7 49#define NM_VECTOR 7
54#define DF_VECTOR 8 50#define DF_VECTOR 8
@@ -342,9 +338,8 @@ struct kvm_vcpu {
342 338
343 struct kvm_guest_debug guest_debug; 339 struct kvm_guest_debug guest_debug;
344 340
345 char fx_buf[FX_BUF_SIZE]; 341 struct i387_fxsave_struct host_fx_image;
346 char *host_fx_image; 342 struct i387_fxsave_struct guest_fx_image;
347 char *guest_fx_image;
348 int fpu_active; 343 int fpu_active;
349 int guest_fpu_loaded; 344 int guest_fpu_loaded;
350 345
@@ -704,12 +699,12 @@ static inline unsigned long read_msr(unsigned long msr)
704} 699}
705#endif 700#endif
706 701
707static inline void fx_save(void *image) 702static inline void fx_save(struct i387_fxsave_struct *image)
708{ 703{
709 asm ("fxsave (%0)":: "r" (image)); 704 asm ("fxsave (%0)":: "r" (image));
710} 705}
711 706
712static inline void fx_restore(void *image) 707static inline void fx_restore(struct i387_fxsave_struct *image)
713{ 708{
714 asm ("fxrstor (%0)":: "r" (image)); 709 asm ("fxrstor (%0)":: "r" (image));
715} 710}
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 4166a08ce500..bfb1b6de0584 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -154,8 +154,8 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
154 return; 154 return;
155 155
156 vcpu->guest_fpu_loaded = 1; 156 vcpu->guest_fpu_loaded = 1;
157 fx_save(vcpu->host_fx_image); 157 fx_save(&vcpu->host_fx_image);
158 fx_restore(vcpu->guest_fx_image); 158 fx_restore(&vcpu->guest_fx_image);
159} 159}
160EXPORT_SYMBOL_GPL(kvm_load_guest_fpu); 160EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
161 161
@@ -165,8 +165,8 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
165 return; 165 return;
166 166
167 vcpu->guest_fpu_loaded = 0; 167 vcpu->guest_fpu_loaded = 0;
168 fx_save(vcpu->guest_fx_image); 168 fx_save(&vcpu->guest_fx_image);
169 fx_restore(vcpu->host_fx_image); 169 fx_restore(&vcpu->host_fx_image);
170} 170}
171EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); 171EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
172 172
@@ -262,10 +262,6 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
262 } 262 }
263 vcpu->pio_data = page_address(page); 263 vcpu->pio_data = page_address(page);
264 264
265 vcpu->host_fx_image = (char*)ALIGN((hva_t)vcpu->fx_buf,
266 FX_IMAGE_ALIGN);
267 vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
268
269 r = kvm_mmu_create(vcpu); 265 r = kvm_mmu_create(vcpu);
270 if (r < 0) 266 if (r < 0)
271 goto fail_free_pio_data; 267 goto fail_free_pio_data;
@@ -615,30 +611,20 @@ EXPORT_SYMBOL_GPL(set_cr8);
615 611
616void fx_init(struct kvm_vcpu *vcpu) 612void fx_init(struct kvm_vcpu *vcpu)
617{ 613{
618 struct __attribute__ ((__packed__)) fx_image_s { 614 unsigned after_mxcsr_mask;
619 u16 control; //fcw
620 u16 status; //fsw
621 u16 tag; // ftw
622 u16 opcode; //fop
623 u64 ip; // fpu ip
624 u64 operand;// fpu dp
625 u32 mxcsr;
626 u32 mxcsr_mask;
627
628 } *fx_image;
629 615
630 /* Initialize guest FPU by resetting ours and saving into guest's */ 616 /* Initialize guest FPU by resetting ours and saving into guest's */
631 preempt_disable(); 617 preempt_disable();
632 fx_save(vcpu->host_fx_image); 618 fx_save(&vcpu->host_fx_image);
633 fpu_init(); 619 fpu_init();
634 fx_save(vcpu->guest_fx_image); 620 fx_save(&vcpu->guest_fx_image);
635 fx_restore(vcpu->host_fx_image); 621 fx_restore(&vcpu->host_fx_image);
636 preempt_enable(); 622 preempt_enable();
637 623
638 fx_image = (struct fx_image_s *)vcpu->guest_fx_image; 624 after_mxcsr_mask = offsetof(struct i387_fxsave_struct, st_space);
639 fx_image->mxcsr = 0x1f80; 625 vcpu->guest_fx_image.mxcsr = 0x1f80;
640 memset(vcpu->guest_fx_image + sizeof(struct fx_image_s), 626 memset((void *)&vcpu->guest_fx_image + after_mxcsr_mask,
641 0, FX_IMAGE_SIZE - sizeof(struct fx_image_s)); 627 0, sizeof(struct i387_fxsave_struct) - after_mxcsr_mask);
642} 628}
643EXPORT_SYMBOL_GPL(fx_init); 629EXPORT_SYMBOL_GPL(fx_init);
644 630
@@ -2356,6 +2342,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
2356 2342
2357 preempt_notifier_init(&vcpu->preempt_notifier, &kvm_preempt_ops); 2343 preempt_notifier_init(&vcpu->preempt_notifier, &kvm_preempt_ops);
2358 2344
2345 /* We do fxsave: this must be aligned. */
2346 BUG_ON((unsigned long)&vcpu->host_fx_image & 0xF);
2347
2359 vcpu_load(vcpu); 2348 vcpu_load(vcpu);
2360 r = kvm_mmu_setup(vcpu); 2349 r = kvm_mmu_setup(vcpu);
2361 vcpu_put(vcpu); 2350 vcpu_put(vcpu);
@@ -2468,7 +2457,7 @@ struct fxsave {
2468 2457
2469static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 2458static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
2470{ 2459{
2471 struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; 2460 struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image;
2472 2461
2473 vcpu_load(vcpu); 2462 vcpu_load(vcpu);
2474 2463
@@ -2488,7 +2477,7 @@ static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
2488 2477
2489static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 2478static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
2490{ 2479{
2491 struct fxsave *fxsave = (struct fxsave *)vcpu->guest_fx_image; 2480 struct fxsave *fxsave = (struct fxsave *)&vcpu->guest_fx_image;
2492 2481
2493 vcpu_load(vcpu); 2482 vcpu_load(vcpu);
2494 2483
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 8193651dd815..5277084f3a35 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -1557,8 +1557,8 @@ again:
1557 } 1557 }
1558 1558
1559 if (vcpu->fpu_active) { 1559 if (vcpu->fpu_active) {
1560 fx_save(vcpu->host_fx_image); 1560 fx_save(&vcpu->host_fx_image);
1561 fx_restore(vcpu->guest_fx_image); 1561 fx_restore(&vcpu->guest_fx_image);
1562 } 1562 }
1563 1563
1564 asm volatile ( 1564 asm volatile (
@@ -1670,8 +1670,8 @@ again:
1670 vcpu->guest_mode = 0; 1670 vcpu->guest_mode = 0;
1671 1671
1672 if (vcpu->fpu_active) { 1672 if (vcpu->fpu_active) {
1673 fx_save(vcpu->guest_fx_image); 1673 fx_save(&vcpu->guest_fx_image);
1674 fx_restore(vcpu->host_fx_image); 1674 fx_restore(&vcpu->host_fx_image);
1675 } 1675 }
1676 1676
1677 if ((svm->vmcb->save.dr7 & 0xff)) 1677 if ((svm->vmcb->save.dr7 & 0xff))