diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-30 07:13:43 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:21 -0400 |
commit | b114b0804df7131cb6764b948c1c530c834fa3c0 (patch) | |
tree | 4e5ced9ed1cdb673d27b26b166cd0bd7c845d5b9 /drivers | |
parent | c16f862d0257349607b7a9be7b4a4b7ed419a3ab (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.h | 13 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 45 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 8 |
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 | ||
707 | static inline void fx_save(void *image) | 702 | static 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 | ||
712 | static inline void fx_restore(void *image) | 707 | static 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 | } |
160 | EXPORT_SYMBOL_GPL(kvm_load_guest_fpu); | 160 | EXPORT_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 | } |
171 | EXPORT_SYMBOL_GPL(kvm_put_guest_fpu); | 171 | EXPORT_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 | ||
616 | void fx_init(struct kvm_vcpu *vcpu) | 612 | void 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 | } |
643 | EXPORT_SYMBOL_GPL(fx_init); | 629 | EXPORT_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 | ||
2469 | static int kvm_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 2458 | static 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 | ||
2489 | static int kvm_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 2478 | static 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)) |